1use alloc::{boxed::Box, vec::Vec};
2use core::{
3 any::Any,
4 fmt::{Debug, Formatter},
5 hash::{Hash, Hasher},
6};
7
8use bevy_reflect_derive::impl_type_path;
9
10use crate::generics::impl_generic_info_methods;
11use crate::{
12 type_info::impl_type_methods, utility::reflect_hasher, ApplyError, FromReflect, Generics,
13 MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type,
14 TypeInfo, TypePath,
15};
16
17pub trait List: PartialReflect {
55 fn get(&self, index: usize) -> Option<&dyn PartialReflect>;
57
58 fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
60
61 fn insert(&mut self, index: usize, element: Box<dyn PartialReflect>);
67
68 fn remove(&mut self, index: usize) -> Box<dyn PartialReflect>;
74
75 fn push(&mut self, value: Box<dyn PartialReflect>) {
77 self.insert(self.len(), value);
78 }
79
80 fn pop(&mut self) -> Option<Box<dyn PartialReflect>> {
82 if self.is_empty() {
83 None
84 } else {
85 Some(self.remove(self.len() - 1))
86 }
87 }
88
89 fn len(&self) -> usize;
91
92 fn is_empty(&self) -> bool {
94 self.len() == 0
95 }
96
97 fn iter(&self) -> ListIter;
99
100 fn drain(&mut self) -> Vec<Box<dyn PartialReflect>>;
105
106 #[deprecated(since = "0.16.0", note = "use `to_dynamic_list` instead")]
108 fn clone_dynamic(&self) -> DynamicList {
109 self.to_dynamic_list()
110 }
111
112 fn to_dynamic_list(&self) -> DynamicList {
114 DynamicList {
115 represented_type: self.get_represented_type_info(),
116 values: self.iter().map(PartialReflect::to_dynamic).collect(),
117 }
118 }
119
120 fn get_represented_list_info(&self) -> Option<&'static ListInfo> {
122 self.get_represented_type_info()?.as_list().ok()
123 }
124}
125
126#[derive(Clone, Debug)]
128pub struct ListInfo {
129 ty: Type,
130 generics: Generics,
131 item_info: fn() -> Option<&'static TypeInfo>,
132 item_ty: Type,
133 #[cfg(feature = "documentation")]
134 docs: Option<&'static str>,
135}
136
137impl ListInfo {
138 pub fn new<TList: List + TypePath, TItem: FromReflect + MaybeTyped + TypePath>() -> Self {
140 Self {
141 ty: Type::of::<TList>(),
142 generics: Generics::new(),
143 item_info: TItem::maybe_type_info,
144 item_ty: Type::of::<TItem>(),
145 #[cfg(feature = "documentation")]
146 docs: None,
147 }
148 }
149
150 #[cfg(feature = "documentation")]
152 pub fn with_docs(self, docs: Option<&'static str>) -> Self {
153 Self { docs, ..self }
154 }
155
156 impl_type_methods!(ty);
157
158 pub fn item_info(&self) -> Option<&'static TypeInfo> {
163 (self.item_info)()
164 }
165
166 pub fn item_ty(&self) -> Type {
170 self.item_ty
171 }
172
173 #[cfg(feature = "documentation")]
175 pub fn docs(&self) -> Option<&'static str> {
176 self.docs
177 }
178
179 impl_generic_info_methods!(generics);
180}
181
182#[derive(Default)]
184pub struct DynamicList {
185 represented_type: Option<&'static TypeInfo>,
186 values: Vec<Box<dyn PartialReflect>>,
187}
188
189impl DynamicList {
190 pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
197 if let Some(represented_type) = represented_type {
198 assert!(
199 matches!(represented_type, TypeInfo::List(_)),
200 "expected TypeInfo::List but received: {:?}",
201 represented_type
202 );
203 }
204
205 self.represented_type = represented_type;
206 }
207
208 pub fn push<T: PartialReflect>(&mut self, value: T) {
210 self.values.push(Box::new(value));
211 }
212
213 pub fn push_box(&mut self, value: Box<dyn PartialReflect>) {
215 self.values.push(value);
216 }
217}
218
219impl List for DynamicList {
220 fn get(&self, index: usize) -> Option<&dyn PartialReflect> {
221 self.values.get(index).map(|value| &**value)
222 }
223
224 fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
225 self.values.get_mut(index).map(|value| &mut **value)
226 }
227
228 fn insert(&mut self, index: usize, element: Box<dyn PartialReflect>) {
229 self.values.insert(index, element);
230 }
231
232 fn remove(&mut self, index: usize) -> Box<dyn PartialReflect> {
233 self.values.remove(index)
234 }
235
236 fn push(&mut self, value: Box<dyn PartialReflect>) {
237 DynamicList::push_box(self, value);
238 }
239
240 fn pop(&mut self) -> Option<Box<dyn PartialReflect>> {
241 self.values.pop()
242 }
243
244 fn len(&self) -> usize {
245 self.values.len()
246 }
247
248 fn iter(&self) -> ListIter {
249 ListIter::new(self)
250 }
251
252 fn drain(&mut self) -> Vec<Box<dyn PartialReflect>> {
253 self.values.drain(..).collect()
254 }
255}
256
257impl PartialReflect for DynamicList {
258 #[inline]
259 fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
260 self.represented_type
261 }
262
263 #[inline]
264 fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
265 self
266 }
267
268 #[inline]
269 fn as_partial_reflect(&self) -> &dyn PartialReflect {
270 self
271 }
272
273 #[inline]
274 fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
275 self
276 }
277
278 fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
279 Err(self)
280 }
281
282 fn try_as_reflect(&self) -> Option<&dyn Reflect> {
283 None
284 }
285
286 fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
287 None
288 }
289
290 fn apply(&mut self, value: &dyn PartialReflect) {
291 list_apply(self, value);
292 }
293
294 fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
295 list_try_apply(self, value)
296 }
297
298 #[inline]
299 fn reflect_kind(&self) -> ReflectKind {
300 ReflectKind::List
301 }
302
303 #[inline]
304 fn reflect_ref(&self) -> ReflectRef {
305 ReflectRef::List(self)
306 }
307
308 #[inline]
309 fn reflect_mut(&mut self) -> ReflectMut {
310 ReflectMut::List(self)
311 }
312
313 #[inline]
314 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
315 ReflectOwned::List(self)
316 }
317
318 #[inline]
319 fn reflect_hash(&self) -> Option<u64> {
320 list_hash(self)
321 }
322
323 fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
324 list_partial_eq(self, value)
325 }
326
327 fn debug(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
328 write!(f, "DynamicList(")?;
329 list_debug(self, f)?;
330 write!(f, ")")
331 }
332
333 #[inline]
334 fn is_dynamic(&self) -> bool {
335 true
336 }
337}
338
339impl_type_path!((in bevy_reflect) DynamicList);
340
341impl Debug for DynamicList {
342 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
343 self.debug(f)
344 }
345}
346
347impl FromIterator<Box<dyn PartialReflect>> for DynamicList {
348 fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(values: I) -> Self {
349 Self {
350 represented_type: None,
351 values: values.into_iter().collect(),
352 }
353 }
354}
355
356impl<T: PartialReflect> FromIterator<T> for DynamicList {
357 fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
358 values
359 .into_iter()
360 .map(|field| Box::new(field).into_partial_reflect())
361 .collect()
362 }
363}
364
365impl IntoIterator for DynamicList {
366 type Item = Box<dyn PartialReflect>;
367 type IntoIter = alloc::vec::IntoIter<Self::Item>;
368
369 fn into_iter(self) -> Self::IntoIter {
370 self.values.into_iter()
371 }
372}
373
374impl<'a> IntoIterator for &'a DynamicList {
375 type Item = &'a dyn PartialReflect;
376 type IntoIter = ListIter<'a>;
377
378 fn into_iter(self) -> Self::IntoIter {
379 self.iter()
380 }
381}
382
383pub struct ListIter<'a> {
385 list: &'a dyn List,
386 index: usize,
387}
388
389impl ListIter<'_> {
390 #[inline]
392 pub const fn new(list: &dyn List) -> ListIter {
393 ListIter { list, index: 0 }
394 }
395}
396
397impl<'a> Iterator for ListIter<'a> {
398 type Item = &'a dyn PartialReflect;
399
400 #[inline]
401 fn next(&mut self) -> Option<Self::Item> {
402 let value = self.list.get(self.index);
403 self.index += value.is_some() as usize;
404 value
405 }
406
407 #[inline]
408 fn size_hint(&self) -> (usize, Option<usize>) {
409 let size = self.list.len();
410 (size, Some(size))
411 }
412}
413
414impl ExactSizeIterator for ListIter<'_> {}
415
416#[inline]
418pub fn list_hash<L: List>(list: &L) -> Option<u64> {
419 let mut hasher = reflect_hasher();
420 Any::type_id(list).hash(&mut hasher);
421 list.len().hash(&mut hasher);
422 for value in list.iter() {
423 hasher.write_u64(value.reflect_hash()?);
424 }
425 Some(hasher.finish())
426}
427
428#[inline]
437pub fn list_apply<L: List>(a: &mut L, b: &dyn PartialReflect) {
438 if let Err(err) = list_try_apply(a, b) {
439 panic!("{err}");
440 }
441}
442
443#[inline]
454pub fn list_try_apply<L: List>(a: &mut L, b: &dyn PartialReflect) -> Result<(), ApplyError> {
455 let list_value = b.reflect_ref().as_list()?;
456
457 for (i, value) in list_value.iter().enumerate() {
458 if i < a.len() {
459 if let Some(v) = a.get_mut(i) {
460 v.try_apply(value)?;
461 }
462 } else {
463 List::push(a, value.to_dynamic());
464 }
465 }
466
467 Ok(())
468}
469
470#[inline]
479pub fn list_partial_eq<L: List + ?Sized>(a: &L, b: &dyn PartialReflect) -> Option<bool> {
480 let ReflectRef::List(list) = b.reflect_ref() else {
481 return Some(false);
482 };
483
484 if a.len() != list.len() {
485 return Some(false);
486 }
487
488 for (a_value, b_value) in a.iter().zip(list.iter()) {
489 let eq_result = a_value.reflect_partial_eq(b_value);
490 if let failed @ (Some(false) | None) = eq_result {
491 return failed;
492 }
493 }
494
495 Some(true)
496}
497
498#[inline]
516pub fn list_debug(dyn_list: &dyn List, f: &mut Formatter<'_>) -> core::fmt::Result {
517 let mut debug = f.debug_list();
518 for item in dyn_list.iter() {
519 debug.entry(&item as &dyn Debug);
520 }
521 debug.finish()
522}
523
524#[cfg(test)]
525mod tests {
526 use super::DynamicList;
527 use crate::Reflect;
528 use alloc::{boxed::Box, vec};
529 use core::assert_eq;
530
531 #[test]
532 fn test_into_iter() {
533 let mut list = DynamicList::default();
534 list.push(0usize);
535 list.push(1usize);
536 list.push(2usize);
537 let items = list.into_iter();
538 for (index, item) in items.into_iter().enumerate() {
539 let value = item
540 .try_take::<usize>()
541 .expect("couldn't downcast to usize");
542 assert_eq!(index, value);
543 }
544 }
545
546 #[test]
547 fn next_index_increment() {
548 const SIZE: usize = if cfg!(debug_assertions) {
549 4
550 } else {
551 usize::MAX
553 };
554 let b = Box::new(vec![(); SIZE]).into_reflect();
555
556 let list = b.reflect_ref().as_list().unwrap();
557
558 let mut iter = list.iter();
559 iter.index = SIZE - 1;
560 assert!(iter.next().is_some());
561
562 assert!(iter.next().is_none());
564 assert!(iter.index == SIZE);
565 assert!(iter.next().is_none());
566 assert!(iter.index == SIZE);
567 }
568}