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 fn to_dynamic_array(&self) -> DynamicArray {
73 DynamicArray {
74 represented_type: self.get_represented_type_info(),
75 values: self.iter().map(PartialReflect::to_dynamic).collect(),
76 }
77 }
78
79 fn get_represented_array_info(&self) -> Option<&'static ArrayInfo> {
81 self.get_represented_type_info()?.as_array().ok()
82 }
83}
84
85#[derive(Clone, Debug)]
87pub struct ArrayInfo {
88 ty: Type,
89 generics: Generics,
90 item_info: fn() -> Option<&'static TypeInfo>,
91 item_ty: Type,
92 capacity: usize,
93 #[cfg(feature = "documentation")]
94 docs: Option<&'static str>,
95}
96
97impl ArrayInfo {
98 pub fn new<TArray: Array + TypePath, TItem: Reflect + MaybeTyped + TypePath>(
104 capacity: usize,
105 ) -> Self {
106 Self {
107 ty: Type::of::<TArray>(),
108 generics: Generics::new(),
109 item_info: TItem::maybe_type_info,
110 item_ty: Type::of::<TItem>(),
111 capacity,
112 #[cfg(feature = "documentation")]
113 docs: None,
114 }
115 }
116
117 #[cfg(feature = "documentation")]
119 pub fn with_docs(self, docs: Option<&'static str>) -> Self {
120 Self { docs, ..self }
121 }
122
123 pub fn capacity(&self) -> usize {
125 self.capacity
126 }
127
128 impl_type_methods!(ty);
129
130 pub fn item_info(&self) -> Option<&'static TypeInfo> {
135 (self.item_info)()
136 }
137
138 pub fn item_ty(&self) -> Type {
142 self.item_ty
143 }
144
145 #[cfg(feature = "documentation")]
147 pub fn docs(&self) -> Option<&'static str> {
148 self.docs
149 }
150
151 impl_generic_info_methods!(generics);
152}
153
154#[derive(Debug)]
164pub struct DynamicArray {
165 pub(crate) represented_type: Option<&'static TypeInfo>,
166 pub(crate) values: Box<[Box<dyn PartialReflect>]>,
167}
168
169impl DynamicArray {
170 #[inline]
172 pub fn new(values: Box<[Box<dyn PartialReflect>]>) -> Self {
173 Self {
174 represented_type: None,
175 values,
176 }
177 }
178
179 pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
187 if let Some(represented_type) = represented_type {
188 assert!(
189 matches!(represented_type, TypeInfo::Array(_)),
190 "expected TypeInfo::Array but received: {represented_type:?}"
191 );
192 }
193
194 self.represented_type = represented_type;
195 }
196}
197
198impl PartialReflect for DynamicArray {
199 #[inline]
200 fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
201 self.represented_type
202 }
203
204 #[inline]
205 fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
206 self
207 }
208
209 #[inline]
210 fn as_partial_reflect(&self) -> &dyn PartialReflect {
211 self
212 }
213
214 #[inline]
215 fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
216 self
217 }
218
219 fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
220 Err(self)
221 }
222
223 fn try_as_reflect(&self) -> Option<&dyn Reflect> {
224 None
225 }
226
227 fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
228 None
229 }
230
231 fn apply(&mut self, value: &dyn PartialReflect) {
232 array_apply(self, value);
233 }
234
235 fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
236 array_try_apply(self, value)
237 }
238
239 #[inline]
240 fn reflect_kind(&self) -> ReflectKind {
241 ReflectKind::Array
242 }
243
244 #[inline]
245 fn reflect_ref(&self) -> ReflectRef<'_> {
246 ReflectRef::Array(self)
247 }
248
249 #[inline]
250 fn reflect_mut(&mut self) -> ReflectMut<'_> {
251 ReflectMut::Array(self)
252 }
253
254 #[inline]
255 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
256 ReflectOwned::Array(self)
257 }
258
259 #[inline]
260 fn reflect_hash(&self) -> Option<u64> {
261 array_hash(self)
262 }
263
264 fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
265 array_partial_eq(self, value)
266 }
267
268 fn debug(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
269 write!(f, "DynamicArray(")?;
270 array_debug(self, f)?;
271 write!(f, ")")
272 }
273
274 #[inline]
275 fn is_dynamic(&self) -> bool {
276 true
277 }
278}
279
280impl Array for DynamicArray {
281 #[inline]
282 fn get(&self, index: usize) -> Option<&dyn PartialReflect> {
283 self.values.get(index).map(|value| &**value)
284 }
285
286 #[inline]
287 fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
288 self.values.get_mut(index).map(|value| &mut **value)
289 }
290
291 #[inline]
292 fn len(&self) -> usize {
293 self.values.len()
294 }
295
296 #[inline]
297 fn iter(&self) -> ArrayIter<'_> {
298 ArrayIter::new(self)
299 }
300
301 #[inline]
302 fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
303 self.values.into_vec()
304 }
305}
306
307impl FromIterator<Box<dyn PartialReflect>> for DynamicArray {
308 fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(values: I) -> Self {
309 Self {
310 represented_type: None,
311 values: values.into_iter().collect::<Vec<_>>().into_boxed_slice(),
312 }
313 }
314}
315
316impl<T: PartialReflect> FromIterator<T> for DynamicArray {
317 fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
318 values
319 .into_iter()
320 .map(|value| Box::new(value).into_partial_reflect())
321 .collect()
322 }
323}
324
325impl IntoIterator for DynamicArray {
326 type Item = Box<dyn PartialReflect>;
327 type IntoIter = alloc::vec::IntoIter<Self::Item>;
328
329 fn into_iter(self) -> Self::IntoIter {
330 self.values.into_vec().into_iter()
331 }
332}
333
334impl<'a> IntoIterator for &'a DynamicArray {
335 type Item = &'a dyn PartialReflect;
336 type IntoIter = ArrayIter<'a>;
337
338 fn into_iter(self) -> Self::IntoIter {
339 self.iter()
340 }
341}
342
343impl_type_path!((in bevy_reflect) DynamicArray);
344
345pub struct ArrayIter<'a> {
347 array: &'a dyn Array,
348 index: usize,
349}
350
351impl ArrayIter<'_> {
352 #[inline]
354 pub const fn new(array: &dyn Array) -> ArrayIter<'_> {
355 ArrayIter { array, index: 0 }
356 }
357}
358
359impl<'a> Iterator for ArrayIter<'a> {
360 type Item = &'a dyn PartialReflect;
361
362 #[inline]
363 fn next(&mut self) -> Option<Self::Item> {
364 let value = self.array.get(self.index);
365 self.index += value.is_some() as usize;
366 value
367 }
368
369 #[inline]
370 fn size_hint(&self) -> (usize, Option<usize>) {
371 let size = self.array.len();
372 (size, Some(size))
373 }
374}
375
376impl<'a> ExactSizeIterator for ArrayIter<'a> {}
377
378#[inline]
380pub fn array_hash<A: Array + ?Sized>(array: &A) -> Option<u64> {
381 let mut hasher = reflect_hasher();
382 Any::type_id(array).hash(&mut hasher);
383 array.len().hash(&mut hasher);
384 for value in array.iter() {
385 hasher.write_u64(value.reflect_hash()?);
386 }
387 Some(hasher.finish())
388}
389
390#[inline]
397pub fn array_apply<A: Array + ?Sized>(array: &mut A, reflect: &dyn PartialReflect) {
398 if let ReflectRef::Array(reflect_array) = reflect.reflect_ref() {
399 if array.len() != reflect_array.len() {
400 panic!("Attempted to apply different sized `Array` types.");
401 }
402 for (i, value) in reflect_array.iter().enumerate() {
403 let v = array.get_mut(i).unwrap();
404 v.apply(value);
405 }
406 } else {
407 panic!("Attempted to apply a non-`Array` type to an `Array` type.");
408 }
409}
410
411#[inline]
421pub fn array_try_apply<A: Array>(
422 array: &mut A,
423 reflect: &dyn PartialReflect,
424) -> Result<(), ApplyError> {
425 let reflect_array = reflect.reflect_ref().as_array()?;
426
427 if array.len() != reflect_array.len() {
428 return Err(ApplyError::DifferentSize {
429 from_size: reflect_array.len(),
430 to_size: array.len(),
431 });
432 }
433
434 for (i, value) in reflect_array.iter().enumerate() {
435 let v = array.get_mut(i).unwrap();
436 v.try_apply(value)?;
437 }
438
439 Ok(())
440}
441
442#[inline]
447pub fn array_partial_eq<A: Array + ?Sized>(
448 array: &A,
449 reflect: &dyn PartialReflect,
450) -> Option<bool> {
451 match reflect.reflect_ref() {
452 ReflectRef::Array(reflect_array) if reflect_array.len() == array.len() => {
453 for (a, b) in array.iter().zip(reflect_array.iter()) {
454 let eq_result = a.reflect_partial_eq(b);
455 if let failed @ (Some(false) | None) = eq_result {
456 return failed;
457 }
458 }
459 }
460 _ => return Some(false),
461 }
462
463 Some(true)
464}
465
466#[inline]
484pub fn array_debug(dyn_array: &dyn Array, f: &mut Formatter<'_>) -> core::fmt::Result {
485 let mut debug = f.debug_list();
486 for item in dyn_array.iter() {
487 debug.entry(&item as &dyn Debug);
488 }
489 debug.finish()
490}
491#[cfg(test)]
492mod tests {
493 use crate::Reflect;
494 use alloc::boxed::Box;
495
496 #[test]
497 fn next_index_increment() {
498 const SIZE: usize = if cfg!(debug_assertions) {
499 4
500 } else {
501 usize::MAX
503 };
504
505 let b = Box::new([(); SIZE]).into_reflect();
506
507 let array = b.reflect_ref().as_array().unwrap();
508
509 let mut iter = array.iter();
510 iter.index = SIZE - 1;
511 assert!(iter.next().is_some());
512
513 assert!(iter.next().is_none());
515 assert!(iter.index == SIZE);
516 assert!(iter.next().is_none());
517 assert!(iter.index == SIZE);
518 }
519}