bevy_reflect/
tuple.rs

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