1use bevy_reflect_derive::impl_type_path;
5use variadics_please::all_tuples;
6
7use crate::generics::impl_generic_info_methods;
8use crate::{
9 ty::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
21pub trait Tuple: PartialReflect {
44 fn field(&self, index: usize) -> Option<&dyn PartialReflect>;
47
48 fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
51
52 fn field_len(&self) -> usize;
54
55 fn iter_fields(&self) -> TupleFieldIter<'_>;
57
58 fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>>;
60
61 fn to_dynamic_tuple(&self) -> Result<DynamicTuple, ReflectCloneError> {
65 Ok(DynamicTuple {
66 represented_type: self.get_represented_type_info(),
67 fields: self
68 .iter_fields()
69 .map(PartialReflect::to_dynamic)
70 .collect::<Result<_, _>>()?,
71 })
72 }
73
74 fn get_represented_tuple_info(&self) -> Option<&'static TupleInfo> {
76 self.get_represented_type_info()?.as_tuple().ok()
77 }
78}
79
80pub struct TupleFieldIter<'a> {
82 pub(crate) tuple: &'a dyn Tuple,
83 pub(crate) index: usize,
84}
85
86impl<'a> TupleFieldIter<'a> {
87 pub fn new(value: &'a dyn Tuple) -> Self {
89 TupleFieldIter {
90 tuple: value,
91 index: 0,
92 }
93 }
94}
95
96impl<'a> Iterator for TupleFieldIter<'a> {
97 type Item = &'a dyn PartialReflect;
98
99 fn next(&mut self) -> Option<Self::Item> {
100 let value = self.tuple.field(self.index);
101 self.index += value.is_some() as usize;
102 value
103 }
104
105 fn size_hint(&self) -> (usize, Option<usize>) {
106 let remaining = self.tuple.field_len().saturating_sub(self.index);
107 (remaining, Some(remaining))
108 }
109}
110
111impl<'a> ExactSizeIterator for TupleFieldIter<'a> {}
112
113pub trait GetTupleField {
129 fn get_field<T: Reflect>(&self, index: usize) -> Option<&T>;
132
133 fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T>;
136}
137
138impl<S: Tuple> GetTupleField for S {
139 fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
140 self.field(index)
141 .and_then(|value| value.try_downcast_ref::<T>())
142 }
143
144 fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
145 self.field_mut(index)
146 .and_then(|value| value.try_downcast_mut::<T>())
147 }
148}
149
150impl GetTupleField for dyn Tuple {
151 fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
152 self.field(index)
153 .and_then(|value| value.try_downcast_ref::<T>())
154 }
155
156 fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
157 self.field_mut(index)
158 .and_then(|value| value.try_downcast_mut::<T>())
159 }
160}
161
162#[derive(Clone, Debug)]
164pub struct TupleInfo {
165 ty: Type,
166 generics: Generics,
167 fields: Box<[UnnamedField]>,
168 #[cfg(feature = "reflect_documentation")]
169 docs: Option<&'static str>,
170}
171
172impl TupleInfo {
173 pub fn new<T: Reflect + TypePath>(fields: &[UnnamedField]) -> Self {
179 Self::from_erased(fields, Type::of::<T>())
180 }
181
182 #[inline(never)]
185 fn from_erased(fields: &[UnnamedField], ty: Type) -> Self {
186 Self {
187 ty,
188 generics: Generics::new(),
189 fields: fields.to_vec().into_boxed_slice(),
190 #[cfg(feature = "reflect_documentation")]
191 docs: None,
192 }
193 }
194
195 #[cfg(feature = "reflect_documentation")]
197 pub fn with_docs(self, docs: Option<&'static str>) -> Self {
198 Self { docs, ..self }
199 }
200
201 pub fn field_at(&self, index: usize) -> Option<&UnnamedField> {
203 self.fields.get(index)
204 }
205
206 pub fn iter(&self) -> Iter<'_, UnnamedField> {
208 self.fields.iter()
209 }
210
211 pub fn field_len(&self) -> usize {
213 self.fields.len()
214 }
215
216 impl_type_methods!(ty);
217
218 #[cfg(feature = "reflect_documentation")]
220 pub fn docs(&self) -> Option<&'static str> {
221 self.docs
222 }
223
224 impl_generic_info_methods!(generics);
225}
226
227#[derive(Default, Debug)]
229pub struct DynamicTuple {
230 represented_type: Option<&'static TypeInfo>,
231 fields: Vec<Box<dyn PartialReflect>>,
232}
233
234impl DynamicTuple {
235 pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
243 if let Some(represented_type) = represented_type {
244 assert!(
245 matches!(represented_type, TypeInfo::Tuple(_)),
246 "expected TypeInfo::Tuple but received: {represented_type:?}"
247 );
248 }
249 self.represented_type = represented_type;
250 }
251
252 pub fn insert_boxed(&mut self, value: Box<dyn PartialReflect>) {
254 self.represented_type = None;
255 self.fields.push(value);
256 }
257
258 pub fn insert<T: PartialReflect>(&mut self, value: T) {
260 self.represented_type = None;
261 self.insert_boxed(Box::new(value));
262 }
263}
264
265impl Tuple for DynamicTuple {
266 #[inline]
267 fn field(&self, index: usize) -> Option<&dyn PartialReflect> {
268 self.fields.get(index).map(|field| &**field)
269 }
270
271 #[inline]
272 fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
273 self.fields.get_mut(index).map(|field| &mut **field)
274 }
275
276 #[inline]
277 fn field_len(&self) -> usize {
278 self.fields.len()
279 }
280
281 #[inline]
282 fn iter_fields(&self) -> TupleFieldIter<'_> {
283 TupleFieldIter {
284 tuple: self,
285 index: 0,
286 }
287 }
288
289 #[inline]
290 fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
291 self.fields
292 }
293}
294
295impl PartialReflect for DynamicTuple {
296 #[inline]
297 fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
298 self.represented_type
299 }
300
301 #[inline]
302 fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
303 self
304 }
305
306 fn as_partial_reflect(&self) -> &dyn PartialReflect {
307 self
308 }
309
310 fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
311 self
312 }
313
314 fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
315 Err(self)
316 }
317
318 fn try_as_reflect(&self) -> Option<&dyn Reflect> {
319 None
320 }
321
322 fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
323 None
324 }
325
326 fn apply(&mut self, value: &dyn PartialReflect) {
327 tuple_apply(self, value);
328 }
329
330 #[inline]
331 fn reflect_kind(&self) -> ReflectKind {
332 ReflectKind::Tuple
333 }
334
335 #[inline]
336 fn reflect_ref(&self) -> ReflectRef<'_> {
337 ReflectRef::Tuple(self)
338 }
339
340 #[inline]
341 fn reflect_mut(&mut self) -> ReflectMut<'_> {
342 ReflectMut::Tuple(self)
343 }
344
345 #[inline]
346 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
347 ReflectOwned::Tuple(self)
348 }
349
350 fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
351 tuple_try_apply(self, value)
352 }
353
354 fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
355 tuple_partial_eq(self, value)
356 }
357
358 fn reflect_partial_cmp(&self, value: &dyn PartialReflect) -> Option<::core::cmp::Ordering> {
359 tuple_partial_cmp(self, value)
360 }
361
362 fn debug(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
363 write!(f, "DynamicTuple(")?;
364 tuple_debug(self, f)?;
365 write!(f, ")")
366 }
367
368 #[inline]
369 fn is_dynamic(&self) -> bool {
370 true
371 }
372}
373
374impl_type_path!((in bevy_reflect) DynamicTuple);
375
376impl FromIterator<Box<dyn PartialReflect>> for DynamicTuple {
377 fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(fields: I) -> Self {
378 Self {
379 represented_type: None,
380 fields: fields.into_iter().collect(),
381 }
382 }
383}
384
385impl IntoIterator for DynamicTuple {
386 type Item = Box<dyn PartialReflect>;
387 type IntoIter = vec::IntoIter<Self::Item>;
388
389 fn into_iter(self) -> Self::IntoIter {
390 self.fields.into_iter()
391 }
392}
393
394impl<'a> IntoIterator for &'a DynamicTuple {
395 type Item = &'a dyn PartialReflect;
396 type IntoIter = TupleFieldIter<'a>;
397
398 fn into_iter(self) -> Self::IntoIter {
399 self.iter_fields()
400 }
401}
402
403#[inline]
409pub fn tuple_apply<T: Tuple>(a: &mut T, b: &dyn PartialReflect) {
410 if let Err(err) = tuple_try_apply(a, b) {
411 panic!("{err}");
412 }
413}
414
415#[inline]
423pub fn tuple_try_apply<T: Tuple>(a: &mut T, b: &dyn PartialReflect) -> Result<(), ApplyError> {
424 let tuple = b.reflect_ref().as_tuple()?;
425
426 for (i, value) in tuple.iter_fields().enumerate() {
427 if let Some(v) = a.field_mut(i) {
428 v.try_apply(value)?;
429 }
430 }
431
432 Ok(())
433}
434
435#[inline]
444pub fn tuple_partial_eq<T: Tuple + ?Sized>(a: &T, b: &dyn PartialReflect) -> Option<bool> {
445 let ReflectRef::Tuple(b) = b.reflect_ref() else {
446 return Some(false);
447 };
448
449 if a.field_len() != b.field_len() {
450 return Some(false);
451 }
452
453 for (a_field, b_field) in a.iter_fields().zip(b.iter_fields()) {
454 let eq_result = a_field.reflect_partial_eq(b_field);
455 if let failed @ (Some(false) | None) = eq_result {
456 return failed;
457 }
458 }
459
460 Some(true)
461}
462
463#[inline]
468pub fn tuple_partial_cmp<T: Tuple + ?Sized>(
469 a: &T,
470 b: &dyn PartialReflect,
471) -> Option<::core::cmp::Ordering> {
472 let ReflectRef::Tuple(b) = b.reflect_ref() else {
473 return None;
474 };
475 if a.field_len() != b.field_len() {
476 return None;
477 }
478
479 for (a_field, b_field) in a.iter_fields().zip(b.iter_fields()) {
480 match a_field.reflect_partial_cmp(b_field) {
481 None => return None,
482 Some(core::cmp::Ordering::Equal) => continue,
483 Some(ord) => return Some(ord),
484 }
485 }
486
487 Some(core::cmp::Ordering::Equal)
488}
489
490#[inline]
508pub fn tuple_debug(dyn_tuple: &dyn Tuple, f: &mut Formatter<'_>) -> core::fmt::Result {
509 let mut debug = f.debug_tuple("");
510 for field in dyn_tuple.iter_fields() {
511 debug.field(&field as &dyn Debug);
512 }
513 debug.finish()
514}
515
516macro_rules! impl_reflect_tuple {
517 {$($index:tt : $name:tt),*} => {
518 impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Tuple for ($($name,)*) {
519 #[inline]
520 fn field(&self, index: usize) -> Option<&dyn PartialReflect> {
521 match index {
522 $($index => Some(&self.$index as &dyn PartialReflect),)*
523 _ => None,
524 }
525 }
526
527 #[inline]
528 fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
529 match index {
530 $($index => Some(&mut self.$index as &mut dyn PartialReflect),)*
531 _ => None,
532 }
533 }
534
535 #[inline]
536 fn field_len(&self) -> usize {
537 let indices: &[usize] = &[$($index as usize),*];
538 indices.len()
539 }
540
541 #[inline]
542 fn iter_fields(&self) -> TupleFieldIter<'_> {
543 TupleFieldIter {
544 tuple: self,
545 index: 0,
546 }
547 }
548
549 #[inline]
550 fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
551 vec![
552 $(Box::new(self.$index),)*
553 ]
554 }
555 }
556
557 impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> PartialReflect for ($($name,)*) {
558 fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
559 Some(<Self as Typed>::type_info())
560 }
561
562 #[inline]
563 fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
564 self
565 }
566
567 fn as_partial_reflect(&self) -> &dyn PartialReflect {
568 self
569 }
570
571 fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
572 self
573 }
574
575 fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
576 Ok(self)
577 }
578
579 fn try_as_reflect(&self) -> Option<&dyn Reflect> {
580 Some(self)
581 }
582
583 fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
584 Some(self)
585 }
586
587 fn reflect_kind(&self) -> ReflectKind {
588 ReflectKind::Tuple
589 }
590
591 fn reflect_ref(&self) -> ReflectRef <'_> {
592 ReflectRef::Tuple(self)
593 }
594
595 fn reflect_mut(&mut self) -> ReflectMut <'_> {
596 ReflectMut::Tuple(self)
597 }
598
599 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
600 ReflectOwned::Tuple(self)
601 }
602
603 fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
604 crate::tuple::tuple_partial_eq(self, value)
605 }
606 fn reflect_partial_cmp(&self, value: &dyn PartialReflect) -> Option<::core::cmp::Ordering> {
607 crate::tuple::tuple_partial_cmp(self, value)
608 }
609
610 fn apply(&mut self, value: &dyn PartialReflect) {
611 crate::tuple::tuple_apply(self, value);
612 }
613
614 fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
615 crate::tuple::tuple_try_apply(self, value)
616 }
617
618 fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
619 Ok(Box::new((
620 $(
621 self.$index.reflect_clone()?
622 .take::<$name>()
623 .expect("`Reflect::reflect_clone` should return the same type"),
624 )*
625 )))
626 }
627 }
628
629 impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Reflect for ($($name,)*) {
630 fn into_any(self: Box<Self>) -> Box<dyn Any> {
631 self
632 }
633
634 fn as_any(&self) -> &dyn Any {
635 self
636 }
637
638 fn as_any_mut(&mut self) -> &mut dyn Any {
639 self
640 }
641
642 fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
643 self
644 }
645
646 fn as_reflect(&self) -> &dyn Reflect {
647 self
648 }
649
650 fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
651 self
652 }
653
654 fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
655 *self = value.take()?;
656 Ok(())
657 }
658 }
659
660 impl <$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Typed for ($($name,)*) {
661 fn type_info() -> &'static TypeInfo {
662 static CELL: $crate::utility::GenericTypeInfoCell = $crate::utility::GenericTypeInfoCell::new();
663 CELL.get_or_insert::<Self, _>(|| {
664 let fields = [
665 $(UnnamedField::new::<$name>($index),)*
666 ];
667 let info = TupleInfo::new::<Self>(&fields);
668 TypeInfo::Tuple(info)
669 })
670 }
671 }
672
673 impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> GetTypeRegistration for ($($name,)*) {
674 fn get_type_registration() -> TypeRegistration {
675 TypeRegistration::of::<($($name,)*)>()
676 }
677
678 fn register_type_dependencies(_registry: &mut TypeRegistry) {
679 $(_registry.register::<$name>();)*
680 }
681 }
682
683 impl<$($name: FromReflect + MaybeTyped + TypePath + GetTypeRegistration),*> FromReflect for ($($name,)*)
684 {
685 fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self> {
686 let _ref_tuple = reflect.reflect_ref().as_tuple().ok()?;
687
688 Some(
689 (
690 $(
691 <$name as FromReflect>::from_reflect(_ref_tuple.field($index)?)?,
692 )*
693 )
694 )
695 }
696 }
697 }
698}
699
700impl_reflect_tuple! {}
701
702impl_reflect_tuple! {0: A}
703
704impl_reflect_tuple! {0: A, 1: B}
705
706impl_reflect_tuple! {0: A, 1: B, 2: C}
707
708impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D}
709
710impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E}
711
712impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F}
713
714impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G}
715
716impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H}
717
718impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I}
719
720impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J}
721
722impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K}
723
724impl_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}
725
726macro_rules! impl_type_path_tuple {
727 ($(#[$meta:meta])*) => {
728 $(#[$meta])*
729 impl TypePath for () {
730 fn type_path() -> &'static str {
731 "()"
732 }
733
734 fn short_type_path() -> &'static str {
735 "()"
736 }
737 }
738 };
739
740 ($(#[$meta:meta])* $param:ident) => {
741 $(#[$meta])*
742 impl <$param: TypePath> TypePath for ($param,) {
743 fn type_path() -> &'static str {
744 use $crate::__macro_exports::alloc_utils::ToOwned;
745 static CELL: GenericTypePathCell = GenericTypePathCell::new();
746 CELL.get_or_insert::<Self, _>(|| {
747 "(".to_owned() + $param::type_path() + ",)"
748 })
749 }
750
751 fn short_type_path() -> &'static str {
752 use $crate::__macro_exports::alloc_utils::ToOwned;
753 static CELL: GenericTypePathCell = GenericTypePathCell::new();
754 CELL.get_or_insert::<Self, _>(|| {
755 "(".to_owned() + $param::short_type_path() + ",)"
756 })
757 }
758 }
759 };
760
761 ($(#[$meta:meta])* $last:ident $(,$param:ident)*) => {
762 $(#[$meta])*
763 impl <$($param: TypePath,)* $last: TypePath> TypePath for ($($param,)* $last) {
764 fn type_path() -> &'static str {
765 use $crate::__macro_exports::alloc_utils::ToOwned;
766 static CELL: GenericTypePathCell = GenericTypePathCell::new();
767 CELL.get_or_insert::<Self, _>(|| {
768 "(".to_owned() $(+ $param::type_path() + ", ")* + $last::type_path() + ")"
769 })
770 }
771
772 fn short_type_path() -> &'static str {
773 use $crate::__macro_exports::alloc_utils::ToOwned;
774 static CELL: GenericTypePathCell = GenericTypePathCell::new();
775 CELL.get_or_insert::<Self, _>(|| {
776 "(".to_owned() $(+ $param::short_type_path() + ", ")* + $last::short_type_path() + ")"
777 })
778 }
779 }
780 };
781}
782
783all_tuples!(
784 #[doc(fake_variadic)]
785 impl_type_path_tuple,
786 0,
787 12,
788 P
789);
790
791#[cfg(feature = "functions")]
792const _: () = {
793 macro_rules! impl_get_ownership_tuple {
794 ($(#[$meta:meta])* $($name: ident),*) => {
795 $(#[$meta])*
796 $crate::func::args::impl_get_ownership!(($($name,)*); <$($name),*>);
797 };
798}
799
800 all_tuples!(
801 #[doc(fake_variadic)]
802 impl_get_ownership_tuple,
803 0,
804 12,
805 P
806 );
807
808 macro_rules! impl_from_arg_tuple {
809 ($(#[$meta:meta])* $($name: ident),*) => {
810 $(#[$meta])*
811 $crate::func::args::impl_from_arg!(($($name,)*); <$($name: FromReflect + MaybeTyped + TypePath + GetTypeRegistration),*>);
812 };
813}
814
815 all_tuples!(
816 #[doc(fake_variadic)]
817 impl_from_arg_tuple,
818 0,
819 12,
820 P
821 );
822
823 macro_rules! impl_into_return_tuple {
824 ($(#[$meta:meta])* $($name: ident),+) => {
825 $(#[$meta])*
826 $crate::func::impl_into_return!(($($name,)*); <$($name: FromReflect + MaybeTyped + TypePath + GetTypeRegistration),*>);
827 };
828}
829
830 all_tuples!(
832 #[doc(fake_variadic)]
833 impl_into_return_tuple,
834 1,
835 12,
836 P
837 );
838};
839
840#[cfg(test)]
841mod tests {
842 use super::Tuple;
843
844 #[test]
845 fn next_index_increment() {
846 let mut iter = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11).iter_fields();
847 let size = iter.len();
848 iter.index = size - 1;
849 let prev_index = iter.index;
850 assert!(iter.next().is_some());
851 assert_eq!(prev_index, iter.index - 1);
852
853 assert!(iter.next().is_none());
855 assert_eq!(size, iter.index);
856 assert!(iter.next().is_none());
857 assert_eq!(size, iter.index);
858 }
859}