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
17pub trait Tuple: PartialReflect {
40 fn field(&self, index: usize) -> Option<&dyn PartialReflect>;
43
44 fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
47
48 fn field_len(&self) -> usize;
50
51 fn iter_fields(&self) -> TupleFieldIter;
53
54 fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>>;
56
57 fn clone_dynamic(&self) -> DynamicTuple;
59
60 fn get_represented_tuple_info(&self) -> Option<&'static TupleInfo> {
62 self.get_represented_type_info()?.as_tuple().ok()
63 }
64}
65
66pub 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
98pub trait GetTupleField {
114 fn get_field<T: Reflect>(&self, index: usize) -> Option<&T>;
117
118 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#[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 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 #[cfg(feature = "documentation")]
175 pub fn with_docs(self, docs: Option<&'static str>) -> Self {
176 Self { docs, ..self }
177 }
178
179 pub fn field_at(&self, index: usize) -> Option<&UnnamedField> {
181 self.fields.get(index)
182 }
183
184 pub fn iter(&self) -> Iter<'_, UnnamedField> {
186 self.fields.iter()
187 }
188
189 pub fn field_len(&self) -> usize {
191 self.fields.len()
192 }
193
194 impl_type_methods!(ty);
195
196 #[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#[derive(Default, Debug)]
207pub struct DynamicTuple {
208 represented_type: Option<&'static TypeInfo>,
209 fields: Vec<Box<dyn PartialReflect>>,
210}
211
212impl DynamicTuple {
213 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 pub fn insert_boxed(&mut self, value: Box<dyn PartialReflect>) {
233 self.represented_type = None;
234 self.fields.push(value);
235 }
236
237 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#[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#[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#[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#[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 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 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}