1use alloc::{boxed::Box, vec::Vec};
5use core::{
6 any::Any,
7 fmt::{Debug, Formatter},
8 hash::{Hash, Hasher},
9};
10
11use bevy_reflect_derive::impl_type_path;
12
13use crate::generics::impl_generic_info_methods;
14use crate::{
15 type_info::impl_type_methods, utility::reflect_hasher, ApplyError, FromReflect, Generics,
16 MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type,
17 TypeInfo, TypePath,
18};
19
20pub trait List: PartialReflect {
58 fn get(&self, index: usize) -> Option<&dyn PartialReflect>;
60
61 fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
63
64 fn insert(&mut self, index: usize, element: Box<dyn PartialReflect>);
70
71 fn remove(&mut self, index: usize) -> Box<dyn PartialReflect>;
77
78 fn push(&mut self, value: Box<dyn PartialReflect>) {
80 self.insert(self.len(), value);
81 }
82
83 fn pop(&mut self) -> Option<Box<dyn PartialReflect>> {
85 if self.is_empty() {
86 None
87 } else {
88 Some(self.remove(self.len() - 1))
89 }
90 }
91
92 fn len(&self) -> usize;
94
95 fn is_empty(&self) -> bool {
97 self.len() == 0
98 }
99
100 fn iter(&self) -> ListIter<'_>;
102
103 fn drain(&mut self) -> Vec<Box<dyn PartialReflect>>;
108
109 fn to_dynamic_list(&self) -> DynamicList {
111 DynamicList {
112 represented_type: self.get_represented_type_info(),
113 values: self.iter().map(PartialReflect::to_dynamic).collect(),
114 }
115 }
116
117 fn get_represented_list_info(&self) -> Option<&'static ListInfo> {
119 self.get_represented_type_info()?.as_list().ok()
120 }
121}
122
123#[derive(Clone, Debug)]
125pub struct ListInfo {
126 ty: Type,
127 generics: Generics,
128 item_info: fn() -> Option<&'static TypeInfo>,
129 item_ty: Type,
130 #[cfg(feature = "reflect_documentation")]
131 docs: Option<&'static str>,
132}
133
134impl ListInfo {
135 pub fn new<TList: List + TypePath, TItem: FromReflect + MaybeTyped + TypePath>() -> Self {
137 Self {
138 ty: Type::of::<TList>(),
139 generics: Generics::new(),
140 item_info: TItem::maybe_type_info,
141 item_ty: Type::of::<TItem>(),
142 #[cfg(feature = "reflect_documentation")]
143 docs: None,
144 }
145 }
146
147 #[cfg(feature = "reflect_documentation")]
149 pub fn with_docs(self, docs: Option<&'static str>) -> Self {
150 Self { docs, ..self }
151 }
152
153 impl_type_methods!(ty);
154
155 pub fn item_info(&self) -> Option<&'static TypeInfo> {
160 (self.item_info)()
161 }
162
163 pub fn item_ty(&self) -> Type {
167 self.item_ty
168 }
169
170 #[cfg(feature = "reflect_documentation")]
172 pub fn docs(&self) -> Option<&'static str> {
173 self.docs
174 }
175
176 impl_generic_info_methods!(generics);
177}
178
179#[derive(Default)]
181pub struct DynamicList {
182 represented_type: Option<&'static TypeInfo>,
183 values: Vec<Box<dyn PartialReflect>>,
184}
185
186impl DynamicList {
187 pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
194 if let Some(represented_type) = represented_type {
195 assert!(
196 matches!(represented_type, TypeInfo::List(_)),
197 "expected TypeInfo::List but received: {represented_type:?}"
198 );
199 }
200
201 self.represented_type = represented_type;
202 }
203
204 pub fn push<T: PartialReflect>(&mut self, value: T) {
206 self.values.push(Box::new(value));
207 }
208
209 pub fn push_box(&mut self, value: Box<dyn PartialReflect>) {
211 self.values.push(value);
212 }
213}
214
215impl List for DynamicList {
216 fn get(&self, index: usize) -> Option<&dyn PartialReflect> {
217 self.values.get(index).map(|value| &**value)
218 }
219
220 fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
221 self.values.get_mut(index).map(|value| &mut **value)
222 }
223
224 fn insert(&mut self, index: usize, element: Box<dyn PartialReflect>) {
225 self.values.insert(index, element);
226 }
227
228 fn remove(&mut self, index: usize) -> Box<dyn PartialReflect> {
229 self.values.remove(index)
230 }
231
232 fn push(&mut self, value: Box<dyn PartialReflect>) {
233 DynamicList::push_box(self, value);
234 }
235
236 fn pop(&mut self) -> Option<Box<dyn PartialReflect>> {
237 self.values.pop()
238 }
239
240 fn len(&self) -> usize {
241 self.values.len()
242 }
243
244 fn iter(&self) -> ListIter<'_> {
245 ListIter::new(self)
246 }
247
248 fn drain(&mut self) -> Vec<Box<dyn PartialReflect>> {
249 self.values.drain(..).collect()
250 }
251}
252
253impl PartialReflect for DynamicList {
254 #[inline]
255 fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
256 self.represented_type
257 }
258
259 #[inline]
260 fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
261 self
262 }
263
264 #[inline]
265 fn as_partial_reflect(&self) -> &dyn PartialReflect {
266 self
267 }
268
269 #[inline]
270 fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
271 self
272 }
273
274 fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
275 Err(self)
276 }
277
278 fn try_as_reflect(&self) -> Option<&dyn Reflect> {
279 None
280 }
281
282 fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
283 None
284 }
285
286 fn apply(&mut self, value: &dyn PartialReflect) {
287 list_apply(self, value);
288 }
289
290 fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
291 list_try_apply(self, value)
292 }
293
294 #[inline]
295 fn reflect_kind(&self) -> ReflectKind {
296 ReflectKind::List
297 }
298
299 #[inline]
300 fn reflect_ref(&self) -> ReflectRef<'_> {
301 ReflectRef::List(self)
302 }
303
304 #[inline]
305 fn reflect_mut(&mut self) -> ReflectMut<'_> {
306 ReflectMut::List(self)
307 }
308
309 #[inline]
310 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
311 ReflectOwned::List(self)
312 }
313
314 #[inline]
315 fn reflect_hash(&self) -> Option<u64> {
316 list_hash(self)
317 }
318
319 fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
320 list_partial_eq(self, value)
321 }
322
323 fn reflect_partial_cmp(&self, value: &dyn PartialReflect) -> Option<::core::cmp::Ordering> {
324 list_partial_cmp(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]
503pub fn list_partial_cmp<L: List + ?Sized>(
504 a: &L,
505 b: &dyn PartialReflect,
506) -> Option<::core::cmp::Ordering> {
507 let ReflectRef::List(list) = b.reflect_ref() else {
508 return None;
509 };
510
511 let min_len = core::cmp::min(a.len(), list.len());
512
513 for (a_value, b_value) in a.iter().zip(list.iter()).take(min_len) {
514 match a_value.reflect_partial_cmp(b_value) {
515 None => return None,
516 Some(core::cmp::Ordering::Equal) => continue,
517 Some(ord) => return Some(ord),
518 }
519 }
520
521 Some(a.len().cmp(&list.len()))
522}
523
524#[inline]
542pub fn list_debug(dyn_list: &dyn List, f: &mut Formatter<'_>) -> core::fmt::Result {
543 let mut debug = f.debug_list();
544 for item in dyn_list.iter() {
545 debug.entry(&item as &dyn Debug);
546 }
547 debug.finish()
548}
549
550#[cfg(test)]
551mod tests {
552 use super::DynamicList;
553 use crate::Reflect;
554 use alloc::{boxed::Box, vec};
555 use core::assert_eq;
556
557 #[test]
558 fn test_into_iter() {
559 let mut list = DynamicList::default();
560 list.push(0usize);
561 list.push(1usize);
562 list.push(2usize);
563 let items = list.into_iter();
564 for (index, item) in items.into_iter().enumerate() {
565 let value = item
566 .try_take::<usize>()
567 .expect("couldn't downcast to usize");
568 assert_eq!(index, value);
569 }
570 }
571
572 #[test]
573 fn next_index_increment() {
574 const SIZE: usize = if cfg!(debug_assertions) {
575 4
576 } else {
577 usize::MAX
579 };
580 let b = Box::new(vec![(); SIZE]).into_reflect();
581
582 let list = b.reflect_ref().as_list().unwrap();
583
584 let mut iter = list.iter();
585 iter.index = SIZE - 1;
586 assert!(iter.next().is_some());
587
588 assert!(iter.next().is_none());
590 assert!(iter.index == SIZE);
591 assert!(iter.next().is_none());
592 assert!(iter.index == SIZE);
593 }
594}