bevy_reflect/
array.rs

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