bevy_reflect/
tuple.rs

1use bevy_reflect_derive::impl_type_path;
2use bevy_utils::all_tuples;
3
4use crate::{
5    self as bevy_reflect, utility::GenericTypePathCell, ApplyError, FromReflect,
6    GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath,
7    TypeRegistration, TypeRegistry, Typed, UnnamedField,
8};
9use crate::{ReflectKind, TypePathTable};
10use std::any::{Any, TypeId};
11use std::fmt::{Debug, Formatter};
12use std::slice::Iter;
13
14/// A trait used to power [tuple-like] operations via [reflection].
15///
16/// This trait uses the [`Reflect`] trait to allow implementors to have their fields
17/// be dynamically addressed by index.
18///
19/// This trait is automatically implemented for arbitrary tuples of up to 12
20/// elements, provided that each element implements [`Reflect`].
21///
22/// # Example
23///
24/// ```
25/// use bevy_reflect::{Reflect, Tuple};
26///
27/// let foo = (123_u32, true);
28/// assert_eq!(foo.field_len(), 2);
29///
30/// let field: &dyn Reflect = foo.field(0).unwrap();
31/// assert_eq!(field.downcast_ref::<u32>(), Some(&123));
32/// ```
33///
34/// [tuple-like]: https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
35/// [reflection]: crate
36pub trait Tuple: Reflect {
37    /// Returns a reference to the value of the field with index `index` as a
38    /// `&dyn Reflect`.
39    fn field(&self, index: usize) -> Option<&dyn Reflect>;
40
41    /// Returns a mutable reference to the value of the field with index `index`
42    /// as a `&mut dyn Reflect`.
43    fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;
44
45    /// Returns the number of fields in the tuple.
46    fn field_len(&self) -> usize;
47
48    /// Returns an iterator over the values of the tuple's fields.
49    fn iter_fields(&self) -> TupleFieldIter;
50
51    /// Drain the fields of this tuple to get a vector of owned values.
52    fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>>;
53
54    /// Clones the struct into a [`DynamicTuple`].
55    fn clone_dynamic(&self) -> DynamicTuple;
56}
57
58/// An iterator over the field values of a tuple.
59pub struct TupleFieldIter<'a> {
60    pub(crate) tuple: &'a dyn Tuple,
61    pub(crate) index: usize,
62}
63
64impl<'a> TupleFieldIter<'a> {
65    pub fn new(value: &'a dyn Tuple) -> Self {
66        TupleFieldIter {
67            tuple: value,
68            index: 0,
69        }
70    }
71}
72
73impl<'a> Iterator for TupleFieldIter<'a> {
74    type Item = &'a dyn Reflect;
75
76    fn next(&mut self) -> Option<Self::Item> {
77        let value = self.tuple.field(self.index);
78        self.index += value.is_some() as usize;
79        value
80    }
81
82    fn size_hint(&self) -> (usize, Option<usize>) {
83        let size = self.tuple.field_len();
84        (size, Some(size))
85    }
86}
87
88impl<'a> ExactSizeIterator for TupleFieldIter<'a> {}
89
90/// A convenience trait which combines fetching and downcasting of tuple
91/// fields.
92///
93/// # Example
94///
95/// ```
96/// use bevy_reflect::GetTupleField;
97///
98/// # fn main() {
99/// let foo = ("blue".to_string(), 42_i32);
100///
101/// assert_eq!(foo.get_field::<String>(0), Some(&"blue".to_string()));
102/// assert_eq!(foo.get_field::<i32>(1), Some(&42));
103/// # }
104/// ```
105pub trait GetTupleField {
106    /// Returns a reference to the value of the field with index `index`,
107    /// downcast to `T`.
108    fn get_field<T: Reflect>(&self, index: usize) -> Option<&T>;
109
110    /// Returns a mutable reference to the value of the field with index
111    /// `index`, downcast to `T`.
112    fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T>;
113}
114
115impl<S: Tuple> GetTupleField for S {
116    fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
117        self.field(index)
118            .and_then(|value| value.downcast_ref::<T>())
119    }
120
121    fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
122        self.field_mut(index)
123            .and_then(|value| value.downcast_mut::<T>())
124    }
125}
126
127impl GetTupleField for dyn Tuple {
128    fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
129        self.field(index)
130            .and_then(|value| value.downcast_ref::<T>())
131    }
132
133    fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
134        self.field_mut(index)
135            .and_then(|value| value.downcast_mut::<T>())
136    }
137}
138
139/// A container for compile-time tuple info.
140#[derive(Clone, Debug)]
141pub struct TupleInfo {
142    type_path: TypePathTable,
143    type_id: TypeId,
144    fields: Box<[UnnamedField]>,
145    #[cfg(feature = "documentation")]
146    docs: Option<&'static str>,
147}
148
149impl TupleInfo {
150    /// Create a new [`TupleInfo`].
151    ///
152    /// # Arguments
153    ///
154    /// * `fields`: The fields of this tuple in the order they are defined
155    ///
156    pub fn new<T: Reflect + TypePath>(fields: &[UnnamedField]) -> Self {
157        Self {
158            type_path: TypePathTable::of::<T>(),
159            type_id: TypeId::of::<T>(),
160            fields: fields.to_vec().into_boxed_slice(),
161            #[cfg(feature = "documentation")]
162            docs: None,
163        }
164    }
165
166    /// Sets the docstring for this tuple.
167    #[cfg(feature = "documentation")]
168    pub fn with_docs(self, docs: Option<&'static str>) -> Self {
169        Self { docs, ..self }
170    }
171
172    /// Get the field at the given index.
173    pub fn field_at(&self, index: usize) -> Option<&UnnamedField> {
174        self.fields.get(index)
175    }
176
177    /// Iterate over the fields of this tuple.
178    pub fn iter(&self) -> Iter<'_, UnnamedField> {
179        self.fields.iter()
180    }
181
182    /// The total number of fields in this tuple.
183    pub fn field_len(&self) -> usize {
184        self.fields.len()
185    }
186
187    /// A representation of the type path of the tuple.
188    ///
189    /// Provides dynamic access to all methods on [`TypePath`].
190    pub fn type_path_table(&self) -> &TypePathTable {
191        &self.type_path
192    }
193
194    /// The [stable, full type path] of the tuple.
195    ///
196    /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`].
197    ///
198    /// [stable, full type path]: TypePath
199    /// [`type_path_table`]: Self::type_path_table
200    pub fn type_path(&self) -> &'static str {
201        self.type_path_table().path()
202    }
203
204    /// The [`TypeId`] of the tuple.
205    pub fn type_id(&self) -> TypeId {
206        self.type_id
207    }
208
209    /// Check if the given type matches the tuple type.
210    pub fn is<T: Any>(&self) -> bool {
211        TypeId::of::<T>() == self.type_id
212    }
213
214    /// The docstring of this tuple, if any.
215    #[cfg(feature = "documentation")]
216    pub fn docs(&self) -> Option<&'static str> {
217        self.docs
218    }
219}
220
221/// A tuple which allows fields to be added at runtime.
222#[derive(Default, Debug)]
223pub struct DynamicTuple {
224    represented_type: Option<&'static TypeInfo>,
225    fields: Vec<Box<dyn Reflect>>,
226}
227
228impl DynamicTuple {
229    /// Sets the [type] to be represented by this `DynamicTuple`.
230    ///
231    /// # Panics
232    ///
233    /// Panics if the given [type] is not a [`TypeInfo::Tuple`].
234    ///
235    /// [type]: TypeInfo
236    pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
237        if let Some(represented_type) = represented_type {
238            assert!(
239                matches!(represented_type, TypeInfo::Tuple(_)),
240                "expected TypeInfo::Tuple but received: {:?}",
241                represented_type
242            );
243        }
244        self.represented_type = represented_type;
245    }
246
247    /// Appends an element with value `value` to the tuple.
248    pub fn insert_boxed(&mut self, value: Box<dyn Reflect>) {
249        self.represented_type = None;
250        self.fields.push(value);
251    }
252
253    /// Appends a typed element with value `value` to the tuple.
254    pub fn insert<T: Reflect>(&mut self, value: T) {
255        self.represented_type = None;
256        self.insert_boxed(Box::new(value));
257    }
258}
259
260impl Tuple for DynamicTuple {
261    #[inline]
262    fn field(&self, index: usize) -> Option<&dyn Reflect> {
263        self.fields.get(index).map(|field| &**field)
264    }
265
266    #[inline]
267    fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
268        self.fields.get_mut(index).map(|field| &mut **field)
269    }
270
271    #[inline]
272    fn field_len(&self) -> usize {
273        self.fields.len()
274    }
275
276    #[inline]
277    fn iter_fields(&self) -> TupleFieldIter {
278        TupleFieldIter {
279            tuple: self,
280            index: 0,
281        }
282    }
283
284    #[inline]
285    fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {
286        self.fields
287    }
288
289    #[inline]
290    fn clone_dynamic(&self) -> DynamicTuple {
291        DynamicTuple {
292            represented_type: self.represented_type,
293            fields: self
294                .fields
295                .iter()
296                .map(|value| value.clone_value())
297                .collect(),
298        }
299    }
300}
301
302impl Reflect for DynamicTuple {
303    #[inline]
304    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
305        self.represented_type
306    }
307
308    #[inline]
309    fn into_any(self: Box<Self>) -> Box<dyn Any> {
310        self
311    }
312
313    #[inline]
314    fn as_any(&self) -> &dyn Any {
315        self
316    }
317
318    #[inline]
319    fn as_any_mut(&mut self) -> &mut dyn Any {
320        self
321    }
322
323    #[inline]
324    fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
325        self
326    }
327
328    #[inline]
329    fn as_reflect(&self) -> &dyn Reflect {
330        self
331    }
332
333    #[inline]
334    fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
335        self
336    }
337
338    fn apply(&mut self, value: &dyn Reflect) {
339        tuple_apply(self, value);
340    }
341
342    fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
343        *self = value.take()?;
344        Ok(())
345    }
346
347    #[inline]
348    fn reflect_kind(&self) -> ReflectKind {
349        ReflectKind::Tuple
350    }
351
352    #[inline]
353    fn reflect_ref(&self) -> ReflectRef {
354        ReflectRef::Tuple(self)
355    }
356
357    #[inline]
358    fn reflect_mut(&mut self) -> ReflectMut {
359        ReflectMut::Tuple(self)
360    }
361
362    #[inline]
363    fn reflect_owned(self: Box<Self>) -> ReflectOwned {
364        ReflectOwned::Tuple(self)
365    }
366
367    #[inline]
368    fn clone_value(&self) -> Box<dyn Reflect> {
369        Box::new(self.clone_dynamic())
370    }
371
372    fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
373        tuple_try_apply(self, value)
374    }
375
376    fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
377        tuple_partial_eq(self, value)
378    }
379
380    fn debug(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
381        write!(f, "DynamicTuple(")?;
382        tuple_debug(self, f)?;
383        write!(f, ")")
384    }
385
386    #[inline]
387    fn is_dynamic(&self) -> bool {
388        true
389    }
390}
391
392impl_type_path!((in bevy_reflect) DynamicTuple);
393
394/// Applies the elements of `b` to the corresponding elements of `a`.
395///
396/// # Panics
397///
398/// This function panics if `b` is not a tuple.
399#[inline]
400pub fn tuple_apply<T: Tuple>(a: &mut T, b: &dyn Reflect) {
401    if let Err(err) = tuple_try_apply(a, b) {
402        panic!("{err}");
403    }
404}
405
406/// Tries to apply the elements of `b` to the corresponding elements of `a` and
407/// returns a Result.
408///
409/// # Errors
410///
411/// This function returns an [`ApplyError::MismatchedKinds`] if `b` is not a tuple or if
412/// applying elements to each other fails.
413#[inline]
414pub fn tuple_try_apply<T: Tuple>(a: &mut T, b: &dyn Reflect) -> Result<(), ApplyError> {
415    if let ReflectRef::Tuple(tuple) = b.reflect_ref() {
416        for (i, value) in tuple.iter_fields().enumerate() {
417            if let Some(v) = a.field_mut(i) {
418                v.try_apply(value)?;
419            }
420        }
421    } else {
422        return Err(ApplyError::MismatchedKinds {
423            from_kind: b.reflect_kind(),
424            to_kind: ReflectKind::Tuple,
425        });
426    }
427    Ok(())
428}
429
430/// Compares a [`Tuple`] with a [`Reflect`] value.
431///
432/// Returns true if and only if all of the following are true:
433/// - `b` is a tuple;
434/// - `b` has the same number of elements as `a`;
435/// - [`Reflect::reflect_partial_eq`] returns `Some(true)` for pairwise elements of `a` and `b`.
436///
437/// Returns [`None`] if the comparison couldn't even be performed.
438#[inline]
439pub fn tuple_partial_eq<T: Tuple>(a: &T, b: &dyn Reflect) -> Option<bool> {
440    let ReflectRef::Tuple(b) = b.reflect_ref() else {
441        return Some(false);
442    };
443
444    if a.field_len() != b.field_len() {
445        return Some(false);
446    }
447
448    for (a_field, b_field) in a.iter_fields().zip(b.iter_fields()) {
449        let eq_result = a_field.reflect_partial_eq(b_field);
450        if let failed @ (Some(false) | None) = eq_result {
451            return failed;
452        }
453    }
454
455    Some(true)
456}
457
458/// The default debug formatter for [`Tuple`] types.
459///
460/// # Example
461/// ```
462/// use bevy_reflect::Reflect;
463///
464/// let my_tuple: &dyn Reflect = &(1, 2, 3);
465/// println!("{:#?}", my_tuple);
466///
467/// // Output:
468///
469/// // (
470/// //   1,
471/// //   2,
472/// //   3,
473/// // )
474/// ```
475#[inline]
476pub fn tuple_debug(dyn_tuple: &dyn Tuple, f: &mut Formatter<'_>) -> std::fmt::Result {
477    let mut debug = f.debug_tuple("");
478    for field in dyn_tuple.iter_fields() {
479        debug.field(&field as &dyn Debug);
480    }
481    debug.finish()
482}
483
484macro_rules! impl_reflect_tuple {
485    {$($index:tt : $name:tt),*} => {
486        impl<$($name: Reflect + TypePath + GetTypeRegistration),*> Tuple for ($($name,)*) {
487            #[inline]
488            fn field(&self, index: usize) -> Option<&dyn Reflect> {
489                match index {
490                    $($index => Some(&self.$index as &dyn Reflect),)*
491                    _ => None,
492                }
493            }
494
495            #[inline]
496            fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
497                match index {
498                    $($index => Some(&mut self.$index as &mut dyn Reflect),)*
499                    _ => None,
500                }
501            }
502
503            #[inline]
504            fn field_len(&self) -> usize {
505                let indices: &[usize] = &[$($index as usize),*];
506                indices.len()
507            }
508
509            #[inline]
510            fn iter_fields(&self) -> TupleFieldIter {
511                TupleFieldIter {
512                    tuple: self,
513                    index: 0,
514                }
515            }
516
517            #[inline]
518            fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {
519                vec![
520                    $(Box::new(self.$index),)*
521                ]
522            }
523
524            #[inline]
525            fn clone_dynamic(&self) -> DynamicTuple {
526                let info = self.get_represented_type_info();
527                DynamicTuple {
528                    represented_type: info,
529                    fields: self
530                        .iter_fields()
531                        .map(|value| value.clone_value())
532                        .collect(),
533                }
534            }
535        }
536
537        impl<$($name: Reflect + TypePath + GetTypeRegistration),*> Reflect for ($($name,)*) {
538            fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
539                Some(<Self as Typed>::type_info())
540            }
541
542            fn into_any(self: Box<Self>) -> Box<dyn Any> {
543                self
544            }
545
546            fn as_any(&self) -> &dyn Any {
547                self
548            }
549
550            fn as_any_mut(&mut self) -> &mut dyn Any {
551                self
552            }
553
554            fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
555                self
556            }
557
558            fn as_reflect(&self) -> &dyn Reflect {
559                self
560            }
561
562            fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
563                self
564            }
565
566            fn apply(&mut self, value: &dyn Reflect) {
567                crate::tuple_apply(self, value);
568            }
569
570            fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
571                crate::tuple_try_apply(self, value)
572            }
573
574            fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
575                *self = value.take()?;
576                Ok(())
577            }
578
579            fn reflect_kind(&self) -> ReflectKind {
580                ReflectKind::Tuple
581            }
582
583            fn reflect_ref(&self) -> ReflectRef {
584                ReflectRef::Tuple(self)
585            }
586
587            fn reflect_mut(&mut self) -> ReflectMut {
588                ReflectMut::Tuple(self)
589            }
590
591            fn reflect_owned(self: Box<Self>) -> ReflectOwned {
592                ReflectOwned::Tuple(self)
593            }
594
595            fn clone_value(&self) -> Box<dyn Reflect> {
596                Box::new(self.clone_dynamic())
597            }
598
599            fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
600                crate::tuple_partial_eq(self, value)
601            }
602        }
603
604        impl <$($name: Reflect + TypePath + GetTypeRegistration),*> Typed for ($($name,)*) {
605            fn type_info() -> &'static TypeInfo {
606                static CELL: $crate::utility::GenericTypeInfoCell = $crate::utility::GenericTypeInfoCell::new();
607                CELL.get_or_insert::<Self, _>(|| {
608                    let fields = [
609                        $(UnnamedField::new::<$name>($index),)*
610                    ];
611                    let info = TupleInfo::new::<Self>(&fields);
612                    TypeInfo::Tuple(info)
613                })
614            }
615        }
616
617        impl<$($name: Reflect + TypePath + GetTypeRegistration),*> GetTypeRegistration for ($($name,)*) {
618            fn get_type_registration() -> TypeRegistration {
619                TypeRegistration::of::<($($name,)*)>()
620            }
621
622            fn register_type_dependencies(_registry: &mut TypeRegistry) {
623                $(_registry.register::<$name>();)*
624            }
625        }
626
627        impl<$($name: FromReflect + TypePath + GetTypeRegistration),*> FromReflect for ($($name,)*)
628        {
629            fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
630                if let ReflectRef::Tuple(_ref_tuple) = reflect.reflect_ref() {
631                    Some(
632                        (
633                            $(
634                                <$name as FromReflect>::from_reflect(_ref_tuple.field($index)?)?,
635                            )*
636                        )
637                    )
638                } else {
639                    None
640                }
641            }
642        }
643    }
644}
645
646impl_reflect_tuple! {}
647impl_reflect_tuple! {0: A}
648impl_reflect_tuple! {0: A, 1: B}
649impl_reflect_tuple! {0: A, 1: B, 2: C}
650impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D}
651impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E}
652impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F}
653impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G}
654impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H}
655impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I}
656impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J}
657impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K}
658impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K, 11: L}
659
660macro_rules! impl_type_path_tuple {
661    () => {
662        impl TypePath for () {
663            fn type_path() -> &'static str {
664                "()"
665            }
666
667            fn short_type_path() -> &'static str {
668                "()"
669            }
670        }
671    };
672
673    ($param:ident) => {
674        impl <$param: TypePath> TypePath for ($param,) {
675            fn type_path() -> &'static str {
676                static CELL: GenericTypePathCell = GenericTypePathCell::new();
677                CELL.get_or_insert::<Self, _>(|| {
678                    "(".to_owned() + $param::type_path() + ",)"
679                })
680            }
681
682            fn short_type_path() -> &'static str {
683                static CELL: GenericTypePathCell = GenericTypePathCell::new();
684                CELL.get_or_insert::<Self, _>(|| {
685                    "(".to_owned() + $param::short_type_path() + ",)"
686                })
687            }
688        }
689    };
690
691    ($last:ident $(,$param:ident)*) => {
692
693        impl <$($param: TypePath,)* $last: TypePath> TypePath for ($($param,)* $last) {
694            fn type_path() -> &'static str {
695                static CELL: GenericTypePathCell = GenericTypePathCell::new();
696                CELL.get_or_insert::<Self, _>(|| {
697                    "(".to_owned() $(+ $param::type_path() + ", ")* + $last::type_path() + ")"
698                })
699            }
700
701            fn short_type_path() -> &'static str {
702                static CELL: GenericTypePathCell = GenericTypePathCell::new();
703                CELL.get_or_insert::<Self, _>(|| {
704                    "(".to_owned() $(+ $param::short_type_path() + ", ")* + $last::short_type_path() + ")"
705                })
706            }
707        }
708    };
709}
710
711all_tuples!(impl_type_path_tuple, 0, 12, P);
712
713#[cfg(test)]
714mod tests {
715    use super::Tuple;
716
717    #[test]
718    fn next_index_increment() {
719        let mut iter = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11).iter_fields();
720        let size = iter.len();
721        iter.index = size - 1;
722        let prev_index = iter.index;
723        assert!(iter.next().is_some());
724        assert_eq!(prev_index, iter.index - 1);
725
726        // When None we should no longer increase index
727        assert!(iter.next().is_none());
728        assert_eq!(size, iter.index);
729        assert!(iter.next().is_none());
730        assert_eq!(size, iter.index);
731    }
732}