bevy_reflect/
array.rs

1use crate::generics::impl_generic_info_methods;
2use crate::{
3    self as bevy_reflect, type_info::impl_type_methods, utility::reflect_hasher, ApplyError,
4    Generics, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned,
5    ReflectRef, Type, TypeInfo, TypePath,
6};
7use bevy_reflect_derive::impl_type_path;
8use core::{
9    any::Any,
10    fmt::{Debug, Formatter},
11    hash::{Hash, Hasher},
12};
13
14/// A trait used to power [array-like] operations via [reflection].
15///
16/// This corresponds to true Rust arrays like `[T; N]`,
17/// but also to any fixed-size linear sequence types.
18/// It is expected that implementors of this trait uphold this contract
19/// and maintain a fixed size as returned by the [`Array::len`] method.
20///
21/// Due to the [type-erasing] nature of the reflection API as a whole,
22/// this trait does not make any guarantees that the implementor's elements
23/// are homogeneous (i.e. all the same type).
24///
25/// This trait has a blanket implementation over Rust arrays of up to 32 items.
26/// This implementation can technically contain more than 32,
27/// but the blanket [`GetTypeRegistration`] is only implemented up to the 32
28/// item limit due to a [limitation] on [`Deserialize`].
29///
30/// # Example
31///
32/// ```
33/// use bevy_reflect::{PartialReflect, Array};
34///
35/// let foo: &dyn Array = &[123_u32, 456_u32, 789_u32];
36/// assert_eq!(foo.len(), 3);
37///
38/// let field: &dyn PartialReflect = foo.get(0).unwrap();
39/// assert_eq!(field.try_downcast_ref::<u32>(), Some(&123));
40/// ```
41///
42/// [array-like]: https://doc.rust-lang.org/book/ch03-02-data-types.html#the-array-type
43/// [reflection]: crate
44/// [`List`]: crate::List
45/// [type-erasing]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html
46/// [`GetTypeRegistration`]: crate::GetTypeRegistration
47/// [limitation]: https://github.com/serde-rs/serde/issues/1937
48/// [`Deserialize`]: ::serde::Deserialize
49pub trait Array: PartialReflect {
50    /// Returns a reference to the element at `index`, or `None` if out of bounds.
51    fn get(&self, index: usize) -> Option<&dyn PartialReflect>;
52
53    /// Returns a mutable reference to the element at `index`, or `None` if out of bounds.
54    fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
55
56    /// Returns the number of elements in the array.
57    fn len(&self) -> usize;
58
59    /// Returns `true` if the collection contains no elements.
60    fn is_empty(&self) -> bool {
61        self.len() == 0
62    }
63
64    /// Returns an iterator over the array.
65    fn iter(&self) -> ArrayIter;
66
67    /// Drain the elements of this array to get a vector of owned values.
68    fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>>;
69
70    /// Clones the list, producing a [`DynamicArray`].
71    fn clone_dynamic(&self) -> DynamicArray {
72        DynamicArray {
73            represented_type: self.get_represented_type_info(),
74            values: self.iter().map(PartialReflect::clone_value).collect(),
75        }
76    }
77
78    /// Will return `None` if [`TypeInfo`] is not available.
79    fn get_represented_array_info(&self) -> Option<&'static ArrayInfo> {
80        self.get_represented_type_info()?.as_array().ok()
81    }
82}
83
84/// A container for compile-time array info.
85#[derive(Clone, Debug)]
86pub struct ArrayInfo {
87    ty: Type,
88    generics: Generics,
89    item_info: fn() -> Option<&'static TypeInfo>,
90    item_ty: Type,
91    capacity: usize,
92    #[cfg(feature = "documentation")]
93    docs: Option<&'static str>,
94}
95
96impl ArrayInfo {
97    /// Create a new [`ArrayInfo`].
98    ///
99    /// # Arguments
100    ///
101    /// * `capacity`: The maximum capacity of the underlying array.
102    pub fn new<TArray: Array + TypePath, TItem: Reflect + MaybeTyped + TypePath>(
103        capacity: usize,
104    ) -> Self {
105        Self {
106            ty: Type::of::<TArray>(),
107            generics: Generics::new(),
108            item_info: TItem::maybe_type_info,
109            item_ty: Type::of::<TItem>(),
110            capacity,
111            #[cfg(feature = "documentation")]
112            docs: None,
113        }
114    }
115
116    /// Sets the docstring for this array.
117    #[cfg(feature = "documentation")]
118    pub fn with_docs(self, docs: Option<&'static str>) -> Self {
119        Self { docs, ..self }
120    }
121
122    /// The compile-time capacity of the array.
123    pub fn capacity(&self) -> usize {
124        self.capacity
125    }
126
127    impl_type_methods!(ty);
128
129    /// The [`TypeInfo`] of the array item.
130    ///
131    /// Returns `None` if the array item does not contain static type information,
132    /// such as for dynamic types.
133    pub fn item_info(&self) -> Option<&'static TypeInfo> {
134        (self.item_info)()
135    }
136
137    /// The [type] of the array item.
138    ///
139    /// [type]: Type
140    pub fn item_ty(&self) -> Type {
141        self.item_ty
142    }
143
144    /// The docstring of this array, if any.
145    #[cfg(feature = "documentation")]
146    pub fn docs(&self) -> Option<&'static str> {
147        self.docs
148    }
149
150    impl_generic_info_methods!(generics);
151}
152
153/// A fixed-size list of reflected values.
154///
155/// This differs from [`DynamicList`] in that the size of the [`DynamicArray`]
156/// is constant, whereas a [`DynamicList`] can have items added and removed.
157///
158/// This isn't to say that a [`DynamicArray`] is immutable— its items
159/// can be mutated— just that the _number_ of items cannot change.
160///
161/// [`DynamicList`]: crate::DynamicList
162#[derive(Debug)]
163pub struct DynamicArray {
164    pub(crate) represented_type: Option<&'static TypeInfo>,
165    pub(crate) values: Box<[Box<dyn PartialReflect>]>,
166}
167
168impl DynamicArray {
169    #[inline]
170    pub fn new(values: Box<[Box<dyn PartialReflect>]>) -> Self {
171        Self {
172            represented_type: None,
173            values,
174        }
175    }
176
177    #[deprecated(since = "0.15.0", note = "use from_iter")]
178    pub fn from_vec<T: PartialReflect>(values: Vec<T>) -> Self {
179        Self::from_iter(values)
180    }
181
182    /// Sets the [type] to be represented by this `DynamicArray`.
183    ///
184    /// # Panics
185    ///
186    /// Panics if the given [type] is not a [`TypeInfo::Array`].
187    ///
188    /// [type]: TypeInfo
189    pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
190        if let Some(represented_type) = represented_type {
191            assert!(
192                matches!(represented_type, TypeInfo::Array(_)),
193                "expected TypeInfo::Array but received: {:?}",
194                represented_type
195            );
196        }
197
198        self.represented_type = represented_type;
199    }
200}
201
202impl PartialReflect for DynamicArray {
203    #[inline]
204    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
205        self.represented_type
206    }
207
208    #[inline]
209    fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
210        self
211    }
212
213    #[inline]
214    fn as_partial_reflect(&self) -> &dyn PartialReflect {
215        self
216    }
217
218    #[inline]
219    fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
220        self
221    }
222
223    fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
224        Err(self)
225    }
226
227    fn try_as_reflect(&self) -> Option<&dyn Reflect> {
228        None
229    }
230
231    fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
232        None
233    }
234
235    fn apply(&mut self, value: &dyn PartialReflect) {
236        array_apply(self, value);
237    }
238
239    fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
240        array_try_apply(self, value)
241    }
242
243    #[inline]
244    fn reflect_kind(&self) -> ReflectKind {
245        ReflectKind::Array
246    }
247
248    #[inline]
249    fn reflect_ref(&self) -> ReflectRef {
250        ReflectRef::Array(self)
251    }
252
253    #[inline]
254    fn reflect_mut(&mut self) -> ReflectMut {
255        ReflectMut::Array(self)
256    }
257
258    #[inline]
259    fn reflect_owned(self: Box<Self>) -> ReflectOwned {
260        ReflectOwned::Array(self)
261    }
262
263    #[inline]
264    fn clone_value(&self) -> Box<dyn PartialReflect> {
265        Box::new(self.clone_dynamic())
266    }
267
268    #[inline]
269    fn reflect_hash(&self) -> Option<u64> {
270        array_hash(self)
271    }
272
273    fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
274        array_partial_eq(self, value)
275    }
276
277    fn debug(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
278        write!(f, "DynamicArray(")?;
279        array_debug(self, f)?;
280        write!(f, ")")
281    }
282
283    #[inline]
284    fn is_dynamic(&self) -> bool {
285        true
286    }
287}
288
289impl Array for DynamicArray {
290    #[inline]
291    fn get(&self, index: usize) -> Option<&dyn PartialReflect> {
292        self.values.get(index).map(|value| &**value)
293    }
294
295    #[inline]
296    fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
297        self.values.get_mut(index).map(|value| &mut **value)
298    }
299
300    #[inline]
301    fn len(&self) -> usize {
302        self.values.len()
303    }
304
305    #[inline]
306    fn iter(&self) -> ArrayIter {
307        ArrayIter::new(self)
308    }
309
310    #[inline]
311    fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
312        self.values.into_vec()
313    }
314
315    #[inline]
316    fn clone_dynamic(&self) -> DynamicArray {
317        DynamicArray {
318            represented_type: self.represented_type,
319            values: self
320                .values
321                .iter()
322                .map(|value| value.clone_value())
323                .collect(),
324        }
325    }
326}
327
328impl FromIterator<Box<dyn PartialReflect>> for DynamicArray {
329    fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(values: I) -> Self {
330        Self {
331            represented_type: None,
332            values: values.into_iter().collect::<Vec<_>>().into_boxed_slice(),
333        }
334    }
335}
336
337impl<T: PartialReflect> FromIterator<T> for DynamicArray {
338    fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
339        values
340            .into_iter()
341            .map(|value| Box::new(value).into_partial_reflect())
342            .collect()
343    }
344}
345
346impl IntoIterator for DynamicArray {
347    type Item = Box<dyn PartialReflect>;
348    type IntoIter = alloc::vec::IntoIter<Self::Item>;
349
350    fn into_iter(self) -> Self::IntoIter {
351        self.values.into_vec().into_iter()
352    }
353}
354
355impl<'a> IntoIterator for &'a DynamicArray {
356    type Item = &'a dyn PartialReflect;
357    type IntoIter = ArrayIter<'a>;
358
359    fn into_iter(self) -> Self::IntoIter {
360        self.iter()
361    }
362}
363
364impl_type_path!((in bevy_reflect) DynamicArray);
365
366/// An iterator over an [`Array`].
367pub struct ArrayIter<'a> {
368    array: &'a dyn Array,
369    index: usize,
370}
371
372impl ArrayIter<'_> {
373    /// Creates a new [`ArrayIter`].
374    #[inline]
375    pub const fn new(array: &dyn Array) -> ArrayIter {
376        ArrayIter { array, index: 0 }
377    }
378}
379
380impl<'a> Iterator for ArrayIter<'a> {
381    type Item = &'a dyn PartialReflect;
382
383    #[inline]
384    fn next(&mut self) -> Option<Self::Item> {
385        let value = self.array.get(self.index);
386        self.index += value.is_some() as usize;
387        value
388    }
389
390    #[inline]
391    fn size_hint(&self) -> (usize, Option<usize>) {
392        let size = self.array.len();
393        (size, Some(size))
394    }
395}
396
397impl<'a> ExactSizeIterator for ArrayIter<'a> {}
398
399/// Returns the `u64` hash of the given [array](Array).
400#[inline]
401pub fn array_hash<A: Array + ?Sized>(array: &A) -> Option<u64> {
402    let mut hasher = reflect_hasher();
403    Any::type_id(array).hash(&mut hasher);
404    array.len().hash(&mut hasher);
405    for value in array.iter() {
406        hasher.write_u64(value.reflect_hash()?);
407    }
408    Some(hasher.finish())
409}
410
411/// Applies the reflected [array](Array) data to the given [array](Array).
412///
413/// # Panics
414///
415/// * Panics if the two arrays have differing lengths.
416/// * Panics if the reflected value is not a [valid array](ReflectRef::Array).
417#[inline]
418pub fn array_apply<A: Array + ?Sized>(array: &mut A, reflect: &dyn PartialReflect) {
419    if let ReflectRef::Array(reflect_array) = reflect.reflect_ref() {
420        if array.len() != reflect_array.len() {
421            panic!("Attempted to apply different sized `Array` types.");
422        }
423        for (i, value) in reflect_array.iter().enumerate() {
424            let v = array.get_mut(i).unwrap();
425            v.apply(value);
426        }
427    } else {
428        panic!("Attempted to apply a non-`Array` type to an `Array` type.");
429    }
430}
431
432/// Tries to apply the reflected [array](Array) data to the given [array](Array) and
433/// returns a Result.
434///
435/// # Errors
436///
437/// * Returns an [`ApplyError::DifferentSize`] if the two arrays have differing lengths.
438/// * Returns an [`ApplyError::MismatchedKinds`] if the reflected value is not a
439///   [valid array](ReflectRef::Array).
440/// * Returns any error that is generated while applying elements to each other.
441#[inline]
442pub fn array_try_apply<A: Array>(
443    array: &mut A,
444    reflect: &dyn PartialReflect,
445) -> Result<(), ApplyError> {
446    let reflect_array = reflect.reflect_ref().as_array()?;
447
448    if array.len() != reflect_array.len() {
449        return Err(ApplyError::DifferentSize {
450            from_size: reflect_array.len(),
451            to_size: array.len(),
452        });
453    }
454
455    for (i, value) in reflect_array.iter().enumerate() {
456        let v = array.get_mut(i).unwrap();
457        v.try_apply(value)?;
458    }
459
460    Ok(())
461}
462
463/// Compares two [arrays](Array) (one concrete and one reflected) to see if they
464/// are equal.
465///
466/// Returns [`None`] if the comparison couldn't even be performed.
467#[inline]
468pub fn array_partial_eq<A: Array + ?Sized>(
469    array: &A,
470    reflect: &dyn PartialReflect,
471) -> Option<bool> {
472    match reflect.reflect_ref() {
473        ReflectRef::Array(reflect_array) if reflect_array.len() == array.len() => {
474            for (a, b) in array.iter().zip(reflect_array.iter()) {
475                let eq_result = a.reflect_partial_eq(b);
476                if let failed @ (Some(false) | None) = eq_result {
477                    return failed;
478                }
479            }
480        }
481        _ => return Some(false),
482    }
483
484    Some(true)
485}
486
487/// The default debug formatter for [`Array`] types.
488///
489/// # Example
490/// ```
491/// use bevy_reflect::Reflect;
492///
493/// let my_array: &dyn Reflect = &[1, 2, 3];
494/// println!("{:#?}", my_array);
495///
496/// // Output:
497///
498/// // [
499/// //   1,
500/// //   2,
501/// //   3,
502/// // ]
503/// ```
504#[inline]
505pub fn array_debug(dyn_array: &dyn Array, f: &mut Formatter<'_>) -> core::fmt::Result {
506    let mut debug = f.debug_list();
507    for item in dyn_array.iter() {
508        debug.entry(&item as &dyn Debug);
509    }
510    debug.finish()
511}
512#[cfg(test)]
513mod tests {
514    use crate::Reflect;
515    #[test]
516    fn next_index_increment() {
517        const SIZE: usize = if cfg!(debug_assertions) {
518            4
519        } else {
520            // If compiled in release mode, verify we dont overflow
521            usize::MAX
522        };
523
524        let b = Box::new([(); SIZE]).into_reflect();
525
526        let array = b.reflect_ref().as_array().unwrap();
527
528        let mut iter = array.iter();
529        iter.index = SIZE - 1;
530        assert!(iter.next().is_some());
531
532        // When None we should no longer increase index
533        assert!(iter.next().is_none());
534        assert!(iter.index == SIZE);
535        assert!(iter.next().is_none());
536        assert!(iter.index == SIZE);
537    }
538}