1use crate::generics::impl_generic_info_methods;
5use crate::{
6 ty::impl_type_methods, utility::reflect_hasher, ApplyError, Generics, MaybeTyped,
7 PartialReflect, Reflect, ReflectCloneError, ReflectKind, ReflectMut, ReflectOwned, ReflectRef,
8 Type, TypeInfo, TypePath,
9};
10use alloc::{boxed::Box, vec::Vec};
11use bevy_reflect_derive::impl_type_path;
12use core::{
13 any::Any,
14 fmt::{Debug, Formatter},
15 hash::{Hash, Hasher},
16};
17
18#[rust_analyzer::completions(ignore_flyimport_methods)]
55pub trait Array: PartialReflect {
56 fn get(&self, index: usize) -> Option<&dyn PartialReflect>;
58
59 fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
61
62 fn len(&self) -> usize;
64
65 fn is_empty(&self) -> bool {
67 self.len() == 0
68 }
69
70 fn iter(&self) -> ArrayIter<'_>;
72
73 fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>>;
75
76 fn to_dynamic_array(&self) -> Result<DynamicArray, ReflectCloneError> {
80 Ok(DynamicArray {
81 represented_type: self.get_represented_type_info(),
82 values: self
83 .iter()
84 .map(PartialReflect::to_dynamic)
85 .collect::<Result<_, _>>()?,
86 })
87 }
88
89 fn get_represented_array_info(&self) -> Option<&'static ArrayInfo> {
91 self.get_represented_type_info()?.as_array().ok()
92 }
93}
94
95#[derive(Clone, Debug)]
97pub struct ArrayInfo {
98 ty: Type,
99 generics: Generics,
100 item_info: fn() -> Option<&'static TypeInfo>,
101 item_ty: Type,
102 capacity: usize,
103 #[cfg(feature = "reflect_documentation")]
104 docs: Option<&'static str>,
105}
106
107impl ArrayInfo {
108 pub fn new<TArray: Array + TypePath, TItem: Reflect + MaybeTyped + TypePath>(
114 capacity: usize,
115 ) -> Self {
116 Self {
117 ty: Type::of::<TArray>(),
118 generics: Generics::new(),
119 item_info: TItem::maybe_type_info,
120 item_ty: Type::of::<TItem>(),
121 capacity,
122 #[cfg(feature = "reflect_documentation")]
123 docs: None,
124 }
125 }
126
127 #[cfg(feature = "reflect_documentation")]
129 pub fn with_docs(self, docs: Option<&'static str>) -> Self {
130 Self { docs, ..self }
131 }
132
133 pub fn capacity(&self) -> usize {
135 self.capacity
136 }
137
138 impl_type_methods!(ty);
139
140 pub fn item_info(&self) -> Option<&'static TypeInfo> {
145 (self.item_info)()
146 }
147
148 pub fn item_ty(&self) -> Type {
152 self.item_ty
153 }
154
155 #[cfg(feature = "reflect_documentation")]
157 pub fn docs(&self) -> Option<&'static str> {
158 self.docs
159 }
160
161 impl_generic_info_methods!(generics);
162}
163
164#[derive(Debug)]
174pub struct DynamicArray {
175 pub(crate) represented_type: Option<&'static TypeInfo>,
176 pub(crate) values: Box<[Box<dyn PartialReflect>]>,
177}
178
179impl DynamicArray {
180 #[inline]
182 pub fn new(values: Box<[Box<dyn PartialReflect>]>) -> Self {
183 Self {
184 represented_type: None,
185 values,
186 }
187 }
188
189 pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
197 if let Some(represented_type) = represented_type {
198 assert!(
199 matches!(represented_type, TypeInfo::Array(_)),
200 "expected TypeInfo::Array but received: {represented_type:?}"
201 );
202 }
203
204 self.represented_type = represented_type;
205 }
206}
207
208impl PartialReflect for DynamicArray {
209 #[inline]
210 fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
211 self.represented_type
212 }
213
214 #[inline]
215 fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
216 self
217 }
218
219 #[inline]
220 fn as_partial_reflect(&self) -> &dyn PartialReflect {
221 self
222 }
223
224 #[inline]
225 fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
226 self
227 }
228
229 fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
230 Err(self)
231 }
232
233 fn try_as_reflect(&self) -> Option<&dyn Reflect> {
234 None
235 }
236
237 fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
238 None
239 }
240
241 fn apply(&mut self, value: &dyn PartialReflect) {
242 array_apply(self, value);
243 }
244
245 fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
246 array_try_apply(self, value)
247 }
248
249 #[inline]
250 fn reflect_kind(&self) -> ReflectKind {
251 ReflectKind::Array
252 }
253
254 #[inline]
255 fn reflect_ref(&self) -> ReflectRef<'_> {
256 ReflectRef::Array(self)
257 }
258
259 #[inline]
260 fn reflect_mut(&mut self) -> ReflectMut<'_> {
261 ReflectMut::Array(self)
262 }
263
264 #[inline]
265 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
266 ReflectOwned::Array(self)
267 }
268
269 #[inline]
270 fn reflect_hash(&self) -> Option<u64> {
271 array_hash(self)
272 }
273
274 fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
275 array_partial_eq(self, value)
276 }
277
278 fn reflect_partial_cmp(&self, value: &dyn PartialReflect) -> Option<::core::cmp::Ordering> {
279 array_partial_cmp(self, value)
280 }
281
282 fn debug(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
283 write!(f, "DynamicArray(")?;
284 array_debug(self, f)?;
285 write!(f, ")")
286 }
287
288 #[inline]
289 fn is_dynamic(&self) -> bool {
290 true
291 }
292}
293
294impl Array for DynamicArray {
295 #[inline]
296 fn get(&self, index: usize) -> Option<&dyn PartialReflect> {
297 self.values.get(index).map(|value| &**value)
298 }
299
300 #[inline]
301 fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
302 self.values.get_mut(index).map(|value| &mut **value)
303 }
304
305 #[inline]
306 fn len(&self) -> usize {
307 self.values.len()
308 }
309
310 #[inline]
311 fn iter(&self) -> ArrayIter<'_> {
312 ArrayIter::new(self)
313 }
314
315 #[inline]
316 fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
317 self.values.into_vec()
318 }
319}
320
321impl FromIterator<Box<dyn PartialReflect>> for DynamicArray {
322 fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(values: I) -> Self {
323 Self {
324 represented_type: None,
325 values: values.into_iter().collect::<Vec<_>>().into_boxed_slice(),
326 }
327 }
328}
329
330impl<T: PartialReflect> FromIterator<T> for DynamicArray {
331 fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
332 values
333 .into_iter()
334 .map(|value| Box::new(value).into_partial_reflect())
335 .collect()
336 }
337}
338
339impl IntoIterator for DynamicArray {
340 type Item = Box<dyn PartialReflect>;
341 type IntoIter = alloc::vec::IntoIter<Self::Item>;
342
343 fn into_iter(self) -> Self::IntoIter {
344 self.values.into_vec().into_iter()
345 }
346}
347
348impl<'a> IntoIterator for &'a DynamicArray {
349 type Item = &'a dyn PartialReflect;
350 type IntoIter = ArrayIter<'a>;
351
352 fn into_iter(self) -> Self::IntoIter {
353 self.iter()
354 }
355}
356
357impl_type_path!((in bevy_reflect) DynamicArray);
358
359pub struct ArrayIter<'a> {
361 array: &'a dyn Array,
362 index: usize,
363}
364
365impl ArrayIter<'_> {
366 #[inline]
368 pub const fn new(array: &dyn Array) -> ArrayIter<'_> {
369 ArrayIter { array, index: 0 }
370 }
371}
372
373impl<'a> Iterator for ArrayIter<'a> {
374 type Item = &'a dyn PartialReflect;
375
376 #[inline]
377 fn next(&mut self) -> Option<Self::Item> {
378 let value = self.array.get(self.index);
379 self.index += value.is_some() as usize;
380 value
381 }
382
383 #[inline]
384 fn size_hint(&self) -> (usize, Option<usize>) {
385 let remaining = self.array.len().saturating_sub(self.index);
386 (remaining, Some(remaining))
387 }
388}
389
390impl<'a> ExactSizeIterator for ArrayIter<'a> {}
391
392#[inline]
394pub fn array_hash<A: Array + ?Sized>(array: &A) -> Option<u64> {
395 let mut hasher = reflect_hasher();
396 Any::type_id(array).hash(&mut hasher);
397 array.len().hash(&mut hasher);
398 for value in array.iter() {
399 hasher.write_u64(value.reflect_hash()?);
400 }
401 Some(hasher.finish())
402}
403
404#[inline]
411pub fn array_apply<A: Array + ?Sized>(array: &mut A, reflect: &dyn PartialReflect) {
412 if let ReflectRef::Array(reflect_array) = reflect.reflect_ref() {
413 if array.len() != reflect_array.len() {
414 panic!("Attempted to apply different sized `Array` types.");
415 }
416 for (i, value) in reflect_array.iter().enumerate() {
417 let v = array.get_mut(i).unwrap();
418 v.apply(value);
419 }
420 } else {
421 panic!("Attempted to apply a non-`Array` type to an `Array` type.");
422 }
423}
424
425#[inline]
435pub fn array_try_apply<A: Array>(
436 array: &mut A,
437 reflect: &dyn PartialReflect,
438) -> Result<(), ApplyError> {
439 let reflect_array = reflect.reflect_ref().as_array()?;
440
441 if array.len() != reflect_array.len() {
442 return Err(ApplyError::DifferentSize {
443 from_size: reflect_array.len(),
444 to_size: array.len(),
445 });
446 }
447
448 for (i, value) in reflect_array.iter().enumerate() {
449 let v = array.get_mut(i).unwrap();
450 v.try_apply(value)?;
451 }
452
453 Ok(())
454}
455
456#[inline]
461pub fn array_partial_eq<A: Array + ?Sized>(
462 array: &A,
463 reflect: &dyn PartialReflect,
464) -> Option<bool> {
465 match reflect.reflect_ref() {
466 ReflectRef::Array(reflect_array) if reflect_array.len() == array.len() => {
467 for (a, b) in array.iter().zip(reflect_array.iter()) {
468 let eq_result = a.reflect_partial_eq(b);
469 if let failed @ (Some(false) | None) = eq_result {
470 return failed;
471 }
472 }
473 }
474 _ => return Some(false),
475 }
476
477 Some(true)
478}
479
480#[inline]
485pub fn array_partial_cmp<A: Array + ?Sized>(
486 array: &A,
487 reflect: &dyn PartialReflect,
488) -> Option<::core::cmp::Ordering> {
489 let ReflectRef::Array(reflect_array) = reflect.reflect_ref() else {
490 return None;
491 };
492
493 let min_len = core::cmp::min(array.len(), reflect_array.len());
494
495 for (a, b) in array.iter().zip(reflect_array.iter()).take(min_len) {
496 match a.reflect_partial_cmp(b) {
497 None => return None,
498 Some(core::cmp::Ordering::Equal) => continue,
499 Some(ord) => return Some(ord),
500 }
501 }
502
503 Some(array.len().cmp(&reflect_array.len()))
505}
506
507#[inline]
525pub fn array_debug(dyn_array: &dyn Array, f: &mut Formatter<'_>) -> core::fmt::Result {
526 let mut debug = f.debug_list();
527 for item in dyn_array.iter() {
528 debug.entry(&item as &dyn Debug);
529 }
530 debug.finish()
531}
532#[cfg(test)]
533mod tests {
534 use crate::Reflect;
535 use alloc::boxed::Box;
536
537 #[test]
538 fn next_index_increment() {
539 const SIZE: usize = if cfg!(debug_assertions) {
540 4
541 } else {
542 usize::MAX
544 };
545
546 let b = Box::new([(); SIZE]).into_reflect();
547
548 let array = b.reflect_ref().as_array().unwrap();
549
550 let mut iter = array.iter();
551 iter.index = SIZE - 1;
552 assert!(iter.next().is_some());
553
554 assert!(iter.next().is_none());
556 assert!(iter.index == SIZE);
557 assert!(iter.next().is_none());
558 assert!(iter.index == SIZE);
559 }
560}