1use crate::generics::impl_generic_info_methods;
2use crate::{
3 self as bevy_reflect, type_info::impl_type_methods, utility::reflect_hasher, ApplyError,
4 Generics, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned,
5 ReflectRef, Type, TypeInfo, TypePath,
6};
7use bevy_reflect_derive::impl_type_path;
8use core::{
9 any::Any,
10 fmt::{Debug, Formatter},
11 hash::{Hash, Hasher},
12};
13
14pub trait Array: PartialReflect {
50 fn get(&self, index: usize) -> Option<&dyn PartialReflect>;
52
53 fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
55
56 fn len(&self) -> usize;
58
59 fn is_empty(&self) -> bool {
61 self.len() == 0
62 }
63
64 fn iter(&self) -> ArrayIter;
66
67 fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>>;
69
70 fn clone_dynamic(&self) -> DynamicArray {
72 DynamicArray {
73 represented_type: self.get_represented_type_info(),
74 values: self.iter().map(PartialReflect::clone_value).collect(),
75 }
76 }
77
78 fn get_represented_array_info(&self) -> Option<&'static ArrayInfo> {
80 self.get_represented_type_info()?.as_array().ok()
81 }
82}
83
84#[derive(Clone, Debug)]
86pub struct ArrayInfo {
87 ty: Type,
88 generics: Generics,
89 item_info: fn() -> Option<&'static TypeInfo>,
90 item_ty: Type,
91 capacity: usize,
92 #[cfg(feature = "documentation")]
93 docs: Option<&'static str>,
94}
95
96impl ArrayInfo {
97 pub fn new<TArray: Array + TypePath, TItem: Reflect + MaybeTyped + TypePath>(
103 capacity: usize,
104 ) -> Self {
105 Self {
106 ty: Type::of::<TArray>(),
107 generics: Generics::new(),
108 item_info: TItem::maybe_type_info,
109 item_ty: Type::of::<TItem>(),
110 capacity,
111 #[cfg(feature = "documentation")]
112 docs: None,
113 }
114 }
115
116 #[cfg(feature = "documentation")]
118 pub fn with_docs(self, docs: Option<&'static str>) -> Self {
119 Self { docs, ..self }
120 }
121
122 pub fn capacity(&self) -> usize {
124 self.capacity
125 }
126
127 impl_type_methods!(ty);
128
129 pub fn item_info(&self) -> Option<&'static TypeInfo> {
134 (self.item_info)()
135 }
136
137 pub fn item_ty(&self) -> Type {
141 self.item_ty
142 }
143
144 #[cfg(feature = "documentation")]
146 pub fn docs(&self) -> Option<&'static str> {
147 self.docs
148 }
149
150 impl_generic_info_methods!(generics);
151}
152
153#[derive(Debug)]
163pub struct DynamicArray {
164 pub(crate) represented_type: Option<&'static TypeInfo>,
165 pub(crate) values: Box<[Box<dyn PartialReflect>]>,
166}
167
168impl DynamicArray {
169 #[inline]
170 pub fn new(values: Box<[Box<dyn PartialReflect>]>) -> Self {
171 Self {
172 represented_type: None,
173 values,
174 }
175 }
176
177 #[deprecated(since = "0.15.0", note = "use from_iter")]
178 pub fn from_vec<T: PartialReflect>(values: Vec<T>) -> Self {
179 Self::from_iter(values)
180 }
181
182 pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
190 if let Some(represented_type) = represented_type {
191 assert!(
192 matches!(represented_type, TypeInfo::Array(_)),
193 "expected TypeInfo::Array but received: {:?}",
194 represented_type
195 );
196 }
197
198 self.represented_type = represented_type;
199 }
200}
201
202impl PartialReflect for DynamicArray {
203 #[inline]
204 fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
205 self.represented_type
206 }
207
208 #[inline]
209 fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
210 self
211 }
212
213 #[inline]
214 fn as_partial_reflect(&self) -> &dyn PartialReflect {
215 self
216 }
217
218 #[inline]
219 fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
220 self
221 }
222
223 fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
224 Err(self)
225 }
226
227 fn try_as_reflect(&self) -> Option<&dyn Reflect> {
228 None
229 }
230
231 fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
232 None
233 }
234
235 fn apply(&mut self, value: &dyn PartialReflect) {
236 array_apply(self, value);
237 }
238
239 fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
240 array_try_apply(self, value)
241 }
242
243 #[inline]
244 fn reflect_kind(&self) -> ReflectKind {
245 ReflectKind::Array
246 }
247
248 #[inline]
249 fn reflect_ref(&self) -> ReflectRef {
250 ReflectRef::Array(self)
251 }
252
253 #[inline]
254 fn reflect_mut(&mut self) -> ReflectMut {
255 ReflectMut::Array(self)
256 }
257
258 #[inline]
259 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
260 ReflectOwned::Array(self)
261 }
262
263 #[inline]
264 fn clone_value(&self) -> Box<dyn PartialReflect> {
265 Box::new(self.clone_dynamic())
266 }
267
268 #[inline]
269 fn reflect_hash(&self) -> Option<u64> {
270 array_hash(self)
271 }
272
273 fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
274 array_partial_eq(self, value)
275 }
276
277 fn debug(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
278 write!(f, "DynamicArray(")?;
279 array_debug(self, f)?;
280 write!(f, ")")
281 }
282
283 #[inline]
284 fn is_dynamic(&self) -> bool {
285 true
286 }
287}
288
289impl Array for DynamicArray {
290 #[inline]
291 fn get(&self, index: usize) -> Option<&dyn PartialReflect> {
292 self.values.get(index).map(|value| &**value)
293 }
294
295 #[inline]
296 fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
297 self.values.get_mut(index).map(|value| &mut **value)
298 }
299
300 #[inline]
301 fn len(&self) -> usize {
302 self.values.len()
303 }
304
305 #[inline]
306 fn iter(&self) -> ArrayIter {
307 ArrayIter::new(self)
308 }
309
310 #[inline]
311 fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
312 self.values.into_vec()
313 }
314
315 #[inline]
316 fn clone_dynamic(&self) -> DynamicArray {
317 DynamicArray {
318 represented_type: self.represented_type,
319 values: self
320 .values
321 .iter()
322 .map(|value| value.clone_value())
323 .collect(),
324 }
325 }
326}
327
328impl FromIterator<Box<dyn PartialReflect>> for DynamicArray {
329 fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(values: I) -> Self {
330 Self {
331 represented_type: None,
332 values: values.into_iter().collect::<Vec<_>>().into_boxed_slice(),
333 }
334 }
335}
336
337impl<T: PartialReflect> FromIterator<T> for DynamicArray {
338 fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
339 values
340 .into_iter()
341 .map(|value| Box::new(value).into_partial_reflect())
342 .collect()
343 }
344}
345
346impl IntoIterator for DynamicArray {
347 type Item = Box<dyn PartialReflect>;
348 type IntoIter = alloc::vec::IntoIter<Self::Item>;
349
350 fn into_iter(self) -> Self::IntoIter {
351 self.values.into_vec().into_iter()
352 }
353}
354
355impl<'a> IntoIterator for &'a DynamicArray {
356 type Item = &'a dyn PartialReflect;
357 type IntoIter = ArrayIter<'a>;
358
359 fn into_iter(self) -> Self::IntoIter {
360 self.iter()
361 }
362}
363
364impl_type_path!((in bevy_reflect) DynamicArray);
365
366pub struct ArrayIter<'a> {
368 array: &'a dyn Array,
369 index: usize,
370}
371
372impl ArrayIter<'_> {
373 #[inline]
375 pub const fn new(array: &dyn Array) -> ArrayIter {
376 ArrayIter { array, index: 0 }
377 }
378}
379
380impl<'a> Iterator for ArrayIter<'a> {
381 type Item = &'a dyn PartialReflect;
382
383 #[inline]
384 fn next(&mut self) -> Option<Self::Item> {
385 let value = self.array.get(self.index);
386 self.index += value.is_some() as usize;
387 value
388 }
389
390 #[inline]
391 fn size_hint(&self) -> (usize, Option<usize>) {
392 let size = self.array.len();
393 (size, Some(size))
394 }
395}
396
397impl<'a> ExactSizeIterator for ArrayIter<'a> {}
398
399#[inline]
401pub fn array_hash<A: Array + ?Sized>(array: &A) -> Option<u64> {
402 let mut hasher = reflect_hasher();
403 Any::type_id(array).hash(&mut hasher);
404 array.len().hash(&mut hasher);
405 for value in array.iter() {
406 hasher.write_u64(value.reflect_hash()?);
407 }
408 Some(hasher.finish())
409}
410
411#[inline]
418pub fn array_apply<A: Array + ?Sized>(array: &mut A, reflect: &dyn PartialReflect) {
419 if let ReflectRef::Array(reflect_array) = reflect.reflect_ref() {
420 if array.len() != reflect_array.len() {
421 panic!("Attempted to apply different sized `Array` types.");
422 }
423 for (i, value) in reflect_array.iter().enumerate() {
424 let v = array.get_mut(i).unwrap();
425 v.apply(value);
426 }
427 } else {
428 panic!("Attempted to apply a non-`Array` type to an `Array` type.");
429 }
430}
431
432#[inline]
442pub fn array_try_apply<A: Array>(
443 array: &mut A,
444 reflect: &dyn PartialReflect,
445) -> Result<(), ApplyError> {
446 let reflect_array = reflect.reflect_ref().as_array()?;
447
448 if array.len() != reflect_array.len() {
449 return Err(ApplyError::DifferentSize {
450 from_size: reflect_array.len(),
451 to_size: array.len(),
452 });
453 }
454
455 for (i, value) in reflect_array.iter().enumerate() {
456 let v = array.get_mut(i).unwrap();
457 v.try_apply(value)?;
458 }
459
460 Ok(())
461}
462
463#[inline]
468pub fn array_partial_eq<A: Array + ?Sized>(
469 array: &A,
470 reflect: &dyn PartialReflect,
471) -> Option<bool> {
472 match reflect.reflect_ref() {
473 ReflectRef::Array(reflect_array) if reflect_array.len() == array.len() => {
474 for (a, b) in array.iter().zip(reflect_array.iter()) {
475 let eq_result = a.reflect_partial_eq(b);
476 if let failed @ (Some(false) | None) = eq_result {
477 return failed;
478 }
479 }
480 }
481 _ => return Some(false),
482 }
483
484 Some(true)
485}
486
487#[inline]
505pub fn array_debug(dyn_array: &dyn Array, f: &mut Formatter<'_>) -> core::fmt::Result {
506 let mut debug = f.debug_list();
507 for item in dyn_array.iter() {
508 debug.entry(&item as &dyn Debug);
509 }
510 debug.finish()
511}
512#[cfg(test)]
513mod tests {
514 use crate::Reflect;
515 #[test]
516 fn next_index_increment() {
517 const SIZE: usize = if cfg!(debug_assertions) {
518 4
519 } else {
520 usize::MAX
522 };
523
524 let b = Box::new([(); SIZE]).into_reflect();
525
526 let array = b.reflect_ref().as_array().unwrap();
527
528 let mut iter = array.iter();
529 iter.index = SIZE - 1;
530 assert!(iter.next().is_some());
531
532 assert!(iter.next().is_none());
534 assert!(iter.index == SIZE);
535 assert!(iter.next().is_none());
536 assert!(iter.index == SIZE);
537 }
538}