Skip to main content

bevy_reflect/
tuple.rs

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