1use bevy_reflect_derive::impl_type_path;
5
6use crate::generics::impl_generic_info_methods;
7use crate::{
8 attributes::{impl_custom_attribute_methods, CustomAttributes},
9 tuple::{DynamicTuple, Tuple},
10 ty::impl_type_methods,
11 ApplyError, Generics, PartialReflect, Reflect, ReflectCloneError, ReflectKind, ReflectMut,
12 ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, UnnamedField,
13};
14use alloc::{boxed::Box, vec::Vec};
15use core::{
16 fmt::{Debug, Formatter},
17 slice::Iter,
18};
19
20pub trait TupleStruct: PartialReflect {
47 fn field(&self, index: usize) -> Option<&dyn PartialReflect>;
50
51 fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
54
55 fn field_len(&self) -> usize;
57
58 fn iter_fields(&self) -> TupleStructFieldIter<'_>;
60
61 fn to_dynamic_tuple_struct(&self) -> Result<DynamicTupleStruct, ReflectCloneError> {
65 Ok(DynamicTupleStruct {
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_struct_info(&self) -> Option<&'static TupleStructInfo> {
76 self.get_represented_type_info()?.as_tuple_struct().ok()
77 }
78}
79
80#[derive(Clone, Debug)]
82pub struct TupleStructInfo {
83 ty: Type,
84 generics: Generics,
85 fields: Box<[UnnamedField]>,
86 custom_attributes: CustomAttributes,
87 #[cfg(feature = "reflect_documentation")]
88 docs: Option<&'static str>,
89}
90
91impl TupleStructInfo {
92 pub fn new<T: Reflect + TypePath>(fields: &[UnnamedField]) -> Self {
98 Self::from_erased(fields, Type::of::<T>())
99 }
100
101 #[inline(never)]
104 fn from_erased(fields: &[UnnamedField], ty: Type) -> Self {
105 Self {
106 ty,
107 generics: Generics::new(),
108 fields: fields.to_vec().into_boxed_slice(),
109 custom_attributes: CustomAttributes::default(),
110 #[cfg(feature = "reflect_documentation")]
111 docs: None,
112 }
113 }
114
115 #[cfg(feature = "reflect_documentation")]
117 pub fn with_docs(self, docs: Option<&'static str>) -> Self {
118 Self { docs, ..self }
119 }
120
121 pub fn with_custom_attributes(self, custom_attributes: CustomAttributes) -> Self {
123 Self {
124 custom_attributes,
125 ..self
126 }
127 }
128
129 pub fn field_at(&self, index: usize) -> Option<&UnnamedField> {
131 self.fields.get(index)
132 }
133
134 pub fn iter(&self) -> Iter<'_, UnnamedField> {
136 self.fields.iter()
137 }
138
139 pub fn field_len(&self) -> usize {
141 self.fields.len()
142 }
143
144 impl_type_methods!(ty);
145
146 #[cfg(feature = "reflect_documentation")]
148 pub fn docs(&self) -> Option<&'static str> {
149 self.docs
150 }
151
152 impl_custom_attribute_methods!(self.custom_attributes, "struct");
153
154 impl_generic_info_methods!(generics);
155}
156
157pub struct TupleStructFieldIter<'a> {
159 pub(crate) tuple_struct: &'a dyn TupleStruct,
160 pub(crate) index: usize,
161}
162
163impl<'a> TupleStructFieldIter<'a> {
164 pub fn new(value: &'a dyn TupleStruct) -> Self {
166 TupleStructFieldIter {
167 tuple_struct: value,
168 index: 0,
169 }
170 }
171}
172
173impl<'a> Iterator for TupleStructFieldIter<'a> {
174 type Item = &'a dyn PartialReflect;
175
176 fn next(&mut self) -> Option<Self::Item> {
177 let value = self.tuple_struct.field(self.index);
178 self.index += value.is_some() as usize;
179 value
180 }
181
182 fn size_hint(&self) -> (usize, Option<usize>) {
183 let remaining = self.tuple_struct.field_len().saturating_sub(self.index);
184 (remaining, Some(remaining))
185 }
186}
187
188impl<'a> ExactSizeIterator for TupleStructFieldIter<'a> {}
189
190pub trait GetTupleStructField {
209 fn get_field<T: Reflect>(&self, index: usize) -> Option<&T>;
212
213 fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T>;
216}
217
218impl<S: TupleStruct> GetTupleStructField for S {
219 fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
220 self.field(index)
221 .and_then(|value| value.try_downcast_ref::<T>())
222 }
223
224 fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
225 self.field_mut(index)
226 .and_then(|value| value.try_downcast_mut::<T>())
227 }
228}
229
230impl GetTupleStructField for dyn TupleStruct {
231 fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
232 self.field(index)
233 .and_then(|value| value.try_downcast_ref::<T>())
234 }
235
236 fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
237 self.field_mut(index)
238 .and_then(|value| value.try_downcast_mut::<T>())
239 }
240}
241
242#[derive(Default)]
244pub struct DynamicTupleStruct {
245 represented_type: Option<&'static TypeInfo>,
246 fields: Vec<Box<dyn PartialReflect>>,
247}
248
249impl DynamicTupleStruct {
250 pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
258 if let Some(represented_type) = represented_type {
259 assert!(
260 matches!(represented_type, TypeInfo::TupleStruct(_)),
261 "expected TypeInfo::TupleStruct but received: {represented_type:?}"
262 );
263 }
264
265 self.represented_type = represented_type;
266 }
267
268 pub fn insert_boxed(&mut self, value: Box<dyn PartialReflect>) {
270 self.fields.push(value);
271 }
272
273 pub fn insert<T: PartialReflect>(&mut self, value: T) {
275 self.insert_boxed(Box::new(value));
276 }
277}
278
279impl TupleStruct for DynamicTupleStruct {
280 #[inline]
281 fn field(&self, index: usize) -> Option<&dyn PartialReflect> {
282 self.fields.get(index).map(|field| &**field)
283 }
284
285 #[inline]
286 fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
287 self.fields.get_mut(index).map(|field| &mut **field)
288 }
289
290 #[inline]
291 fn field_len(&self) -> usize {
292 self.fields.len()
293 }
294
295 #[inline]
296 fn iter_fields(&self) -> TupleStructFieldIter<'_> {
297 TupleStructFieldIter {
298 tuple_struct: self,
299 index: 0,
300 }
301 }
302}
303
304impl PartialReflect for DynamicTupleStruct {
305 #[inline]
306 fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
307 self.represented_type
308 }
309
310 #[inline]
311 fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
312 self
313 }
314
315 #[inline]
316 fn as_partial_reflect(&self) -> &dyn PartialReflect {
317 self
318 }
319
320 #[inline]
321 fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
322 self
323 }
324
325 fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
326 Err(self)
327 }
328
329 fn try_as_reflect(&self) -> Option<&dyn Reflect> {
330 None
331 }
332
333 fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
334 None
335 }
336
337 fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
338 let tuple_struct = value.reflect_ref().as_tuple_struct()?;
339
340 for (i, value) in tuple_struct.iter_fields().enumerate() {
341 if let Some(v) = self.field_mut(i) {
342 v.try_apply(value)?;
343 }
344 }
345
346 Ok(())
347 }
348
349 #[inline]
350 fn reflect_kind(&self) -> ReflectKind {
351 ReflectKind::TupleStruct
352 }
353
354 #[inline]
355 fn reflect_ref(&self) -> ReflectRef<'_> {
356 ReflectRef::TupleStruct(self)
357 }
358
359 #[inline]
360 fn reflect_mut(&mut self) -> ReflectMut<'_> {
361 ReflectMut::TupleStruct(self)
362 }
363
364 #[inline]
365 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
366 ReflectOwned::TupleStruct(self)
367 }
368
369 #[inline]
370 fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
371 tuple_struct_partial_eq(self, value)
372 }
373
374 fn reflect_partial_cmp(&self, value: &dyn PartialReflect) -> Option<::core::cmp::Ordering> {
375 tuple_struct_partial_cmp(self, value)
376 }
377
378 fn debug(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
379 write!(f, "DynamicTupleStruct(")?;
380 tuple_struct_debug(self, f)?;
381 write!(f, ")")
382 }
383
384 #[inline]
385 fn is_dynamic(&self) -> bool {
386 true
387 }
388}
389
390impl_type_path!((in bevy_reflect) DynamicTupleStruct);
391
392impl Debug for DynamicTupleStruct {
393 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
394 self.debug(f)
395 }
396}
397
398impl From<DynamicTuple> for DynamicTupleStruct {
399 fn from(value: DynamicTuple) -> Self {
400 Self {
401 represented_type: None,
402 fields: Box::new(value).drain(),
403 }
404 }
405}
406
407impl FromIterator<Box<dyn PartialReflect>> for DynamicTupleStruct {
408 fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(fields: I) -> Self {
409 Self {
410 represented_type: None,
411 fields: fields.into_iter().collect(),
412 }
413 }
414}
415
416impl IntoIterator for DynamicTupleStruct {
417 type Item = Box<dyn PartialReflect>;
418 type IntoIter = alloc::vec::IntoIter<Self::Item>;
419
420 fn into_iter(self) -> Self::IntoIter {
421 self.fields.into_iter()
422 }
423}
424
425impl<'a> IntoIterator for &'a DynamicTupleStruct {
426 type Item = &'a dyn PartialReflect;
427 type IntoIter = TupleStructFieldIter<'a>;
428
429 fn into_iter(self) -> Self::IntoIter {
430 self.iter_fields()
431 }
432}
433
434#[inline(never)]
443pub fn tuple_struct_partial_eq(a: &dyn TupleStruct, b: &dyn PartialReflect) -> Option<bool> {
444 let ReflectRef::TupleStruct(tuple_struct) = b.reflect_ref() else {
445 return Some(false);
446 };
447
448 if a.field_len() != tuple_struct.field_len() {
449 return Some(false);
450 }
451
452 for (i, value) in tuple_struct.iter_fields().enumerate() {
453 if let Some(field_value) = a.field(i) {
454 let eq_result = field_value.reflect_partial_eq(value);
455 if let failed @ (Some(false) | None) = eq_result {
456 return failed;
457 }
458 } else {
459 return Some(false);
460 }
461 }
462
463 Some(true)
464}
465#[inline(never)]
470pub fn tuple_struct_partial_cmp(
471 a: &dyn TupleStruct,
472 b: &dyn PartialReflect,
473) -> Option<::core::cmp::Ordering> {
474 let ReflectRef::TupleStruct(tuple_struct) = b.reflect_ref() else {
475 return None;
476 };
477
478 if a.field_len() != tuple_struct.field_len() {
479 return None;
480 }
481
482 for (i, value) in tuple_struct.iter_fields().enumerate() {
483 if let Some(field_value) = a.field(i) {
484 match field_value.reflect_partial_cmp(value) {
485 None => return None,
486 Some(core::cmp::Ordering::Equal) => continue,
487 Some(ord) => return Some(ord),
488 }
489 }
490 return None;
491 }
492
493 Some(core::cmp::Ordering::Equal)
494}
495
496#[inline]
514pub fn tuple_struct_debug(
515 dyn_tuple_struct: &dyn TupleStruct,
516 f: &mut Formatter<'_>,
517) -> core::fmt::Result {
518 let mut debug = f.debug_tuple(
519 dyn_tuple_struct
520 .get_represented_type_info()
521 .map(TypeInfo::type_path)
522 .unwrap_or("_"),
523 );
524 for field in dyn_tuple_struct.iter_fields() {
525 debug.field(&field as &dyn Debug);
526 }
527 debug.finish()
528}
529
530#[cfg(test)]
531mod tests {
532 use super::TupleStruct;
533 use crate::Reflect;
534 #[derive(Reflect)]
535 struct Ts(u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8);
536 #[test]
537 fn next_index_increment() {
538 let mut iter = Ts(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11).iter_fields();
539 let size = iter.len();
540 iter.index = size - 1;
541 let prev_index = iter.index;
542 assert!(iter.next().is_some());
543 assert_eq!(prev_index, iter.index - 1);
544
545 assert!(iter.next().is_none());
547 assert_eq!(size, iter.index);
548 assert!(iter.next().is_none());
549 assert_eq!(size, iter.index);
550 }
551}