bevy_reflect/
tuple.rs

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