1use crate::generics::impl_generic_info_methods;
2use crate::{
3 type_info::impl_type_methods, utility::reflect_hasher, ApplyError, Generics, MaybeTyped,
4 PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type, TypeInfo,
5 TypePath,
6};
7use alloc::{boxed::Box, vec::Vec};
8use bevy_reflect_derive::impl_type_path;
9use core::{
10 any::Any,
11 fmt::{Debug, Formatter},
12 hash::{Hash, Hasher},
13};
14
15pub trait Array: PartialReflect {
51 fn get(&self, index: usize) -> Option<&dyn PartialReflect>;
53
54 fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
56
57 fn len(&self) -> usize;
59
60 fn is_empty(&self) -> bool {
62 self.len() == 0
63 }
64
65 fn iter(&self) -> ArrayIter;
67
68 fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>>;
70
71 #[deprecated(since = "0.16.0", note = "use `to_dynamic_array` instead")]
73 fn clone_dynamic(&self) -> DynamicArray {
74 self.to_dynamic_array()
75 }
76
77 fn to_dynamic_array(&self) -> DynamicArray {
79 DynamicArray {
80 represented_type: self.get_represented_type_info(),
81 values: self.iter().map(PartialReflect::to_dynamic).collect(),
82 }
83 }
84
85 fn get_represented_array_info(&self) -> Option<&'static ArrayInfo> {
87 self.get_represented_type_info()?.as_array().ok()
88 }
89}
90
91#[derive(Clone, Debug)]
93pub struct ArrayInfo {
94 ty: Type,
95 generics: Generics,
96 item_info: fn() -> Option<&'static TypeInfo>,
97 item_ty: Type,
98 capacity: usize,
99 #[cfg(feature = "documentation")]
100 docs: Option<&'static str>,
101}
102
103impl ArrayInfo {
104 pub fn new<TArray: Array + TypePath, TItem: Reflect + MaybeTyped + TypePath>(
110 capacity: usize,
111 ) -> Self {
112 Self {
113 ty: Type::of::<TArray>(),
114 generics: Generics::new(),
115 item_info: TItem::maybe_type_info,
116 item_ty: Type::of::<TItem>(),
117 capacity,
118 #[cfg(feature = "documentation")]
119 docs: None,
120 }
121 }
122
123 #[cfg(feature = "documentation")]
125 pub fn with_docs(self, docs: Option<&'static str>) -> Self {
126 Self { docs, ..self }
127 }
128
129 pub fn capacity(&self) -> usize {
131 self.capacity
132 }
133
134 impl_type_methods!(ty);
135
136 pub fn item_info(&self) -> Option<&'static TypeInfo> {
141 (self.item_info)()
142 }
143
144 pub fn item_ty(&self) -> Type {
148 self.item_ty
149 }
150
151 #[cfg(feature = "documentation")]
153 pub fn docs(&self) -> Option<&'static str> {
154 self.docs
155 }
156
157 impl_generic_info_methods!(generics);
158}
159
160#[derive(Debug)]
170pub struct DynamicArray {
171 pub(crate) represented_type: Option<&'static TypeInfo>,
172 pub(crate) values: Box<[Box<dyn PartialReflect>]>,
173}
174
175impl DynamicArray {
176 #[inline]
177 pub fn new(values: Box<[Box<dyn PartialReflect>]>) -> Self {
178 Self {
179 represented_type: None,
180 values,
181 }
182 }
183
184 pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
192 if let Some(represented_type) = represented_type {
193 assert!(
194 matches!(represented_type, TypeInfo::Array(_)),
195 "expected TypeInfo::Array but received: {:?}",
196 represented_type
197 );
198 }
199
200 self.represented_type = represented_type;
201 }
202}
203
204impl PartialReflect for DynamicArray {
205 #[inline]
206 fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
207 self.represented_type
208 }
209
210 #[inline]
211 fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
212 self
213 }
214
215 #[inline]
216 fn as_partial_reflect(&self) -> &dyn PartialReflect {
217 self
218 }
219
220 #[inline]
221 fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
222 self
223 }
224
225 fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
226 Err(self)
227 }
228
229 fn try_as_reflect(&self) -> Option<&dyn Reflect> {
230 None
231 }
232
233 fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
234 None
235 }
236
237 fn apply(&mut self, value: &dyn PartialReflect) {
238 array_apply(self, value);
239 }
240
241 fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
242 array_try_apply(self, value)
243 }
244
245 #[inline]
246 fn reflect_kind(&self) -> ReflectKind {
247 ReflectKind::Array
248 }
249
250 #[inline]
251 fn reflect_ref(&self) -> ReflectRef {
252 ReflectRef::Array(self)
253 }
254
255 #[inline]
256 fn reflect_mut(&mut self) -> ReflectMut {
257 ReflectMut::Array(self)
258 }
259
260 #[inline]
261 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
262 ReflectOwned::Array(self)
263 }
264
265 #[inline]
266 fn reflect_hash(&self) -> Option<u64> {
267 array_hash(self)
268 }
269
270 fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
271 array_partial_eq(self, value)
272 }
273
274 fn debug(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
275 write!(f, "DynamicArray(")?;
276 array_debug(self, f)?;
277 write!(f, ")")
278 }
279
280 #[inline]
281 fn is_dynamic(&self) -> bool {
282 true
283 }
284}
285
286impl Array for DynamicArray {
287 #[inline]
288 fn get(&self, index: usize) -> Option<&dyn PartialReflect> {
289 self.values.get(index).map(|value| &**value)
290 }
291
292 #[inline]
293 fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
294 self.values.get_mut(index).map(|value| &mut **value)
295 }
296
297 #[inline]
298 fn len(&self) -> usize {
299 self.values.len()
300 }
301
302 #[inline]
303 fn iter(&self) -> ArrayIter {
304 ArrayIter::new(self)
305 }
306
307 #[inline]
308 fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
309 self.values.into_vec()
310 }
311}
312
313impl FromIterator<Box<dyn PartialReflect>> for DynamicArray {
314 fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(values: I) -> Self {
315 Self {
316 represented_type: None,
317 values: values.into_iter().collect::<Vec<_>>().into_boxed_slice(),
318 }
319 }
320}
321
322impl<T: PartialReflect> FromIterator<T> for DynamicArray {
323 fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
324 values
325 .into_iter()
326 .map(|value| Box::new(value).into_partial_reflect())
327 .collect()
328 }
329}
330
331impl IntoIterator for DynamicArray {
332 type Item = Box<dyn PartialReflect>;
333 type IntoIter = alloc::vec::IntoIter<Self::Item>;
334
335 fn into_iter(self) -> Self::IntoIter {
336 self.values.into_vec().into_iter()
337 }
338}
339
340impl<'a> IntoIterator for &'a DynamicArray {
341 type Item = &'a dyn PartialReflect;
342 type IntoIter = ArrayIter<'a>;
343
344 fn into_iter(self) -> Self::IntoIter {
345 self.iter()
346 }
347}
348
349impl_type_path!((in bevy_reflect) DynamicArray);
350
351pub struct ArrayIter<'a> {
353 array: &'a dyn Array,
354 index: usize,
355}
356
357impl ArrayIter<'_> {
358 #[inline]
360 pub const fn new(array: &dyn Array) -> ArrayIter {
361 ArrayIter { array, index: 0 }
362 }
363}
364
365impl<'a> Iterator for ArrayIter<'a> {
366 type Item = &'a dyn PartialReflect;
367
368 #[inline]
369 fn next(&mut self) -> Option<Self::Item> {
370 let value = self.array.get(self.index);
371 self.index += value.is_some() as usize;
372 value
373 }
374
375 #[inline]
376 fn size_hint(&self) -> (usize, Option<usize>) {
377 let size = self.array.len();
378 (size, Some(size))
379 }
380}
381
382impl<'a> ExactSizeIterator for ArrayIter<'a> {}
383
384#[inline]
386pub fn array_hash<A: Array + ?Sized>(array: &A) -> Option<u64> {
387 let mut hasher = reflect_hasher();
388 Any::type_id(array).hash(&mut hasher);
389 array.len().hash(&mut hasher);
390 for value in array.iter() {
391 hasher.write_u64(value.reflect_hash()?);
392 }
393 Some(hasher.finish())
394}
395
396#[inline]
403pub fn array_apply<A: Array + ?Sized>(array: &mut A, reflect: &dyn PartialReflect) {
404 if let ReflectRef::Array(reflect_array) = reflect.reflect_ref() {
405 if array.len() != reflect_array.len() {
406 panic!("Attempted to apply different sized `Array` types.");
407 }
408 for (i, value) in reflect_array.iter().enumerate() {
409 let v = array.get_mut(i).unwrap();
410 v.apply(value);
411 }
412 } else {
413 panic!("Attempted to apply a non-`Array` type to an `Array` type.");
414 }
415}
416
417#[inline]
427pub fn array_try_apply<A: Array>(
428 array: &mut A,
429 reflect: &dyn PartialReflect,
430) -> Result<(), ApplyError> {
431 let reflect_array = reflect.reflect_ref().as_array()?;
432
433 if array.len() != reflect_array.len() {
434 return Err(ApplyError::DifferentSize {
435 from_size: reflect_array.len(),
436 to_size: array.len(),
437 });
438 }
439
440 for (i, value) in reflect_array.iter().enumerate() {
441 let v = array.get_mut(i).unwrap();
442 v.try_apply(value)?;
443 }
444
445 Ok(())
446}
447
448#[inline]
453pub fn array_partial_eq<A: Array + ?Sized>(
454 array: &A,
455 reflect: &dyn PartialReflect,
456) -> Option<bool> {
457 match reflect.reflect_ref() {
458 ReflectRef::Array(reflect_array) if reflect_array.len() == array.len() => {
459 for (a, b) in array.iter().zip(reflect_array.iter()) {
460 let eq_result = a.reflect_partial_eq(b);
461 if let failed @ (Some(false) | None) = eq_result {
462 return failed;
463 }
464 }
465 }
466 _ => return Some(false),
467 }
468
469 Some(true)
470}
471
472#[inline]
490pub fn array_debug(dyn_array: &dyn Array, f: &mut Formatter<'_>) -> core::fmt::Result {
491 let mut debug = f.debug_list();
492 for item in dyn_array.iter() {
493 debug.entry(&item as &dyn Debug);
494 }
495 debug.finish()
496}
497#[cfg(test)]
498mod tests {
499 use crate::Reflect;
500 use alloc::boxed::Box;
501
502 #[test]
503 fn next_index_increment() {
504 const SIZE: usize = if cfg!(debug_assertions) {
505 4
506 } else {
507 usize::MAX
509 };
510
511 let b = Box::new([(); SIZE]).into_reflect();
512
513 let array = b.reflect_ref().as_array().unwrap();
514
515 let mut iter = array.iter();
516 iter.index = SIZE - 1;
517 assert!(iter.next().is_some());
518
519 assert!(iter.next().is_none());
521 assert!(iter.index == SIZE);
522 assert!(iter.next().is_none());
523 assert!(iter.index == SIZE);
524 }
525}