1use bevy_reflect_derive::impl_type_path;
2
3use crate::generics::impl_generic_info_methods;
4use crate::{
5 self as bevy_reflect,
6 attributes::{impl_custom_attribute_methods, CustomAttributes},
7 type_info::impl_type_methods,
8 ApplyError, DynamicTuple, Generics, PartialReflect, Reflect, ReflectKind, ReflectMut,
9 ReflectOwned, ReflectRef, Tuple, Type, TypeInfo, TypePath, UnnamedField,
10};
11use alloc::sync::Arc;
12use core::{
13 fmt::{Debug, Formatter},
14 slice::Iter,
15};
16
17pub trait TupleStruct: 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) -> TupleStructFieldIter;
57
58 fn clone_dynamic(&self) -> DynamicTupleStruct;
60
61 fn get_represented_tuple_struct_info(&self) -> Option<&'static TupleStructInfo> {
63 self.get_represented_type_info()?.as_tuple_struct().ok()
64 }
65}
66
67#[derive(Clone, Debug)]
69pub struct TupleStructInfo {
70 ty: Type,
71 generics: Generics,
72 fields: Box<[UnnamedField]>,
73 custom_attributes: Arc<CustomAttributes>,
74 #[cfg(feature = "documentation")]
75 docs: Option<&'static str>,
76}
77
78impl TupleStructInfo {
79 pub fn new<T: Reflect + TypePath>(fields: &[UnnamedField]) -> Self {
85 Self {
86 ty: Type::of::<T>(),
87 generics: Generics::new(),
88 fields: fields.to_vec().into_boxed_slice(),
89 custom_attributes: Arc::new(CustomAttributes::default()),
90 #[cfg(feature = "documentation")]
91 docs: None,
92 }
93 }
94
95 #[cfg(feature = "documentation")]
97 pub fn with_docs(self, docs: Option<&'static str>) -> Self {
98 Self { docs, ..self }
99 }
100
101 pub fn with_custom_attributes(self, custom_attributes: CustomAttributes) -> Self {
103 Self {
104 custom_attributes: Arc::new(custom_attributes),
105 ..self
106 }
107 }
108
109 pub fn field_at(&self, index: usize) -> Option<&UnnamedField> {
111 self.fields.get(index)
112 }
113
114 pub fn iter(&self) -> Iter<'_, UnnamedField> {
116 self.fields.iter()
117 }
118
119 pub fn field_len(&self) -> usize {
121 self.fields.len()
122 }
123
124 impl_type_methods!(ty);
125
126 #[cfg(feature = "documentation")]
128 pub fn docs(&self) -> Option<&'static str> {
129 self.docs
130 }
131
132 impl_custom_attribute_methods!(self.custom_attributes, "struct");
133
134 impl_generic_info_methods!(generics);
135}
136
137pub struct TupleStructFieldIter<'a> {
139 pub(crate) tuple_struct: &'a dyn TupleStruct,
140 pub(crate) index: usize,
141}
142
143impl<'a> TupleStructFieldIter<'a> {
144 pub fn new(value: &'a dyn TupleStruct) -> Self {
145 TupleStructFieldIter {
146 tuple_struct: value,
147 index: 0,
148 }
149 }
150}
151
152impl<'a> Iterator for TupleStructFieldIter<'a> {
153 type Item = &'a dyn PartialReflect;
154
155 fn next(&mut self) -> Option<Self::Item> {
156 let value = self.tuple_struct.field(self.index);
157 self.index += value.is_some() as usize;
158 value
159 }
160
161 fn size_hint(&self) -> (usize, Option<usize>) {
162 let size = self.tuple_struct.field_len();
163 (size, Some(size))
164 }
165}
166
167impl<'a> ExactSizeIterator for TupleStructFieldIter<'a> {}
168
169pub trait GetTupleStructField {
188 fn get_field<T: Reflect>(&self, index: usize) -> Option<&T>;
191
192 fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T>;
195}
196
197impl<S: TupleStruct> GetTupleStructField for S {
198 fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
199 self.field(index)
200 .and_then(|value| value.try_downcast_ref::<T>())
201 }
202
203 fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
204 self.field_mut(index)
205 .and_then(|value| value.try_downcast_mut::<T>())
206 }
207}
208
209impl GetTupleStructField for dyn TupleStruct {
210 fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
211 self.field(index)
212 .and_then(|value| value.try_downcast_ref::<T>())
213 }
214
215 fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
216 self.field_mut(index)
217 .and_then(|value| value.try_downcast_mut::<T>())
218 }
219}
220
221#[derive(Default)]
223pub struct DynamicTupleStruct {
224 represented_type: Option<&'static TypeInfo>,
225 fields: Vec<Box<dyn PartialReflect>>,
226}
227
228impl DynamicTupleStruct {
229 pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
237 if let Some(represented_type) = represented_type {
238 assert!(
239 matches!(represented_type, TypeInfo::TupleStruct(_)),
240 "expected TypeInfo::TupleStruct but received: {:?}",
241 represented_type
242 );
243 }
244
245 self.represented_type = represented_type;
246 }
247
248 pub fn insert_boxed(&mut self, value: Box<dyn PartialReflect>) {
250 self.fields.push(value);
251 }
252
253 pub fn insert<T: PartialReflect>(&mut self, value: T) {
255 self.insert_boxed(Box::new(value));
256 }
257}
258
259impl TupleStruct for DynamicTupleStruct {
260 #[inline]
261 fn field(&self, index: usize) -> Option<&dyn PartialReflect> {
262 self.fields.get(index).map(|field| &**field)
263 }
264
265 #[inline]
266 fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
267 self.fields.get_mut(index).map(|field| &mut **field)
268 }
269
270 #[inline]
271 fn field_len(&self) -> usize {
272 self.fields.len()
273 }
274
275 #[inline]
276 fn iter_fields(&self) -> TupleStructFieldIter {
277 TupleStructFieldIter {
278 tuple_struct: self,
279 index: 0,
280 }
281 }
282
283 fn clone_dynamic(&self) -> DynamicTupleStruct {
284 DynamicTupleStruct {
285 represented_type: self.represented_type,
286 fields: self
287 .fields
288 .iter()
289 .map(|value| value.clone_value())
290 .collect(),
291 }
292 }
293}
294
295impl PartialReflect for DynamicTupleStruct {
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 #[inline]
307 fn as_partial_reflect(&self) -> &dyn PartialReflect {
308 self
309 }
310
311 #[inline]
312 fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
313 self
314 }
315
316 fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
317 Err(self)
318 }
319
320 fn try_as_reflect(&self) -> Option<&dyn Reflect> {
321 None
322 }
323
324 fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
325 None
326 }
327
328 fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
329 let tuple_struct = value.reflect_ref().as_tuple_struct()?;
330
331 for (i, value) in tuple_struct.iter_fields().enumerate() {
332 if let Some(v) = self.field_mut(i) {
333 v.try_apply(value)?;
334 }
335 }
336
337 Ok(())
338 }
339
340 #[inline]
341 fn reflect_kind(&self) -> ReflectKind {
342 ReflectKind::TupleStruct
343 }
344
345 #[inline]
346 fn reflect_ref(&self) -> ReflectRef {
347 ReflectRef::TupleStruct(self)
348 }
349
350 #[inline]
351 fn reflect_mut(&mut self) -> ReflectMut {
352 ReflectMut::TupleStruct(self)
353 }
354
355 #[inline]
356 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
357 ReflectOwned::TupleStruct(self)
358 }
359
360 #[inline]
361 fn clone_value(&self) -> Box<dyn PartialReflect> {
362 Box::new(self.clone_dynamic())
363 }
364
365 #[inline]
366 fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
367 tuple_struct_partial_eq(self, value)
368 }
369
370 fn debug(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
371 write!(f, "DynamicTupleStruct(")?;
372 tuple_struct_debug(self, f)?;
373 write!(f, ")")
374 }
375
376 #[inline]
377 fn is_dynamic(&self) -> bool {
378 true
379 }
380}
381
382impl_type_path!((in bevy_reflect) DynamicTupleStruct);
383
384impl Debug for DynamicTupleStruct {
385 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
386 self.debug(f)
387 }
388}
389
390impl From<DynamicTuple> for DynamicTupleStruct {
391 fn from(value: DynamicTuple) -> Self {
392 Self {
393 represented_type: None,
394 fields: Box::new(value).drain(),
395 }
396 }
397}
398
399impl FromIterator<Box<dyn PartialReflect>> for DynamicTupleStruct {
400 fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(fields: I) -> Self {
401 Self {
402 represented_type: None,
403 fields: fields.into_iter().collect(),
404 }
405 }
406}
407
408impl IntoIterator for DynamicTupleStruct {
409 type Item = Box<dyn PartialReflect>;
410 type IntoIter = alloc::vec::IntoIter<Self::Item>;
411
412 fn into_iter(self) -> Self::IntoIter {
413 self.fields.into_iter()
414 }
415}
416
417impl<'a> IntoIterator for &'a DynamicTupleStruct {
418 type Item = &'a dyn PartialReflect;
419 type IntoIter = TupleStructFieldIter<'a>;
420
421 fn into_iter(self) -> Self::IntoIter {
422 self.iter_fields()
423 }
424}
425
426#[inline]
435pub fn tuple_struct_partial_eq<S: TupleStruct + ?Sized>(
436 a: &S,
437 b: &dyn PartialReflect,
438) -> Option<bool> {
439 let ReflectRef::TupleStruct(tuple_struct) = b.reflect_ref() else {
440 return Some(false);
441 };
442
443 if a.field_len() != tuple_struct.field_len() {
444 return Some(false);
445 }
446
447 for (i, value) in tuple_struct.iter_fields().enumerate() {
448 if let Some(field_value) = a.field(i) {
449 let eq_result = field_value.reflect_partial_eq(value);
450 if let failed @ (Some(false) | None) = eq_result {
451 return failed;
452 }
453 } else {
454 return Some(false);
455 }
456 }
457
458 Some(true)
459}
460
461#[inline]
479pub fn tuple_struct_debug(
480 dyn_tuple_struct: &dyn TupleStruct,
481 f: &mut Formatter<'_>,
482) -> core::fmt::Result {
483 let mut debug = f.debug_tuple(
484 dyn_tuple_struct
485 .get_represented_type_info()
486 .map(TypeInfo::type_path)
487 .unwrap_or("_"),
488 );
489 for field in dyn_tuple_struct.iter_fields() {
490 debug.field(&field as &dyn Debug);
491 }
492 debug.finish()
493}
494
495#[cfg(test)]
496mod tests {
497 use crate as bevy_reflect;
498 use crate::*;
499 #[derive(Reflect)]
500 struct Ts(u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8);
501 #[test]
502 fn next_index_increment() {
503 let mut iter = Ts(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11).iter_fields();
504 let size = iter.len();
505 iter.index = size - 1;
506 let prev_index = iter.index;
507 assert!(iter.next().is_some());
508 assert_eq!(prev_index, iter.index - 1);
509
510 assert!(iter.next().is_none());
512 assert_eq!(size, iter.index);
513 assert!(iter.next().is_none());
514 assert_eq!(size, iter.index);
515 }
516}