1use crate::{
2 self as bevy_reflect, utility::reflect_hasher, ApplyError, Reflect, ReflectKind, ReflectMut,
3 ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable,
4};
5use bevy_reflect_derive::impl_type_path;
6use std::{
7 any::{Any, TypeId},
8 fmt::{Debug, Formatter},
9 hash::{Hash, Hasher},
10};
11
12pub trait Array: Reflect {
48 fn get(&self, index: usize) -> Option<&dyn Reflect>;
50
51 fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;
53
54 fn len(&self) -> usize;
56
57 fn is_empty(&self) -> bool {
59 self.len() == 0
60 }
61
62 fn iter(&self) -> ArrayIter;
64
65 fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>>;
67
68 fn clone_dynamic(&self) -> DynamicArray {
70 DynamicArray {
71 represented_type: self.get_represented_type_info(),
72 values: self.iter().map(|value| value.clone_value()).collect(),
73 }
74 }
75}
76
77#[derive(Clone, Debug)]
79pub struct ArrayInfo {
80 type_path: TypePathTable,
81 type_id: TypeId,
82 item_type_path: TypePathTable,
83 item_type_id: TypeId,
84 capacity: usize,
85 #[cfg(feature = "documentation")]
86 docs: Option<&'static str>,
87}
88
89impl ArrayInfo {
90 pub fn new<TArray: Array + TypePath, TItem: Reflect + TypePath>(capacity: usize) -> Self {
97 Self {
98 type_path: TypePathTable::of::<TArray>(),
99 type_id: TypeId::of::<TArray>(),
100 item_type_path: TypePathTable::of::<TItem>(),
101 item_type_id: TypeId::of::<TItem>(),
102 capacity,
103 #[cfg(feature = "documentation")]
104 docs: None,
105 }
106 }
107
108 #[cfg(feature = "documentation")]
110 pub fn with_docs(self, docs: Option<&'static str>) -> Self {
111 Self { docs, ..self }
112 }
113
114 pub fn capacity(&self) -> usize {
116 self.capacity
117 }
118
119 pub fn type_path_table(&self) -> &TypePathTable {
123 &self.type_path
124 }
125
126 pub fn type_path(&self) -> &'static str {
133 self.type_path_table().path()
134 }
135
136 pub fn type_id(&self) -> TypeId {
138 self.type_id
139 }
140
141 pub fn is<T: Any>(&self) -> bool {
143 TypeId::of::<T>() == self.type_id
144 }
145
146 pub fn item_type_path_table(&self) -> &TypePathTable {
150 &self.item_type_path
151 }
152
153 pub fn item_type_id(&self) -> TypeId {
155 self.item_type_id
156 }
157
158 pub fn item_is<T: Any>(&self) -> bool {
160 TypeId::of::<T>() == self.item_type_id
161 }
162
163 #[cfg(feature = "documentation")]
165 pub fn docs(&self) -> Option<&'static str> {
166 self.docs
167 }
168}
169
170#[derive(Debug)]
180pub struct DynamicArray {
181 pub(crate) represented_type: Option<&'static TypeInfo>,
182 pub(crate) values: Box<[Box<dyn Reflect>]>,
183}
184
185impl DynamicArray {
186 #[inline]
187 pub fn new(values: Box<[Box<dyn Reflect>]>) -> Self {
188 Self {
189 represented_type: None,
190 values,
191 }
192 }
193
194 pub fn from_vec<T: Reflect>(values: Vec<T>) -> Self {
195 Self {
196 represented_type: None,
197 values: values
198 .into_iter()
199 .map(|field| Box::new(field) as Box<dyn Reflect>)
200 .collect::<Vec<_>>()
201 .into_boxed_slice(),
202 }
203 }
204
205 pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
213 if let Some(represented_type) = represented_type {
214 assert!(
215 matches!(represented_type, TypeInfo::Array(_)),
216 "expected TypeInfo::Array but received: {:?}",
217 represented_type
218 );
219 }
220
221 self.represented_type = represented_type;
222 }
223}
224
225impl Reflect for DynamicArray {
226 #[inline]
227 fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
228 self.represented_type
229 }
230
231 #[inline]
232 fn into_any(self: Box<Self>) -> Box<dyn Any> {
233 self
234 }
235
236 #[inline]
237 fn as_any(&self) -> &dyn Any {
238 self
239 }
240
241 #[inline]
242 fn as_any_mut(&mut self) -> &mut dyn Any {
243 self
244 }
245
246 #[inline]
247 fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
248 self
249 }
250
251 #[inline]
252 fn as_reflect(&self) -> &dyn Reflect {
253 self
254 }
255
256 #[inline]
257 fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
258 self
259 }
260
261 fn apply(&mut self, value: &dyn Reflect) {
262 array_apply(self, value);
263 }
264
265 fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
266 array_try_apply(self, value)
267 }
268
269 #[inline]
270 fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
271 *self = value.take()?;
272 Ok(())
273 }
274
275 #[inline]
276 fn reflect_kind(&self) -> ReflectKind {
277 ReflectKind::Array
278 }
279
280 #[inline]
281 fn reflect_ref(&self) -> ReflectRef {
282 ReflectRef::Array(self)
283 }
284
285 #[inline]
286 fn reflect_mut(&mut self) -> ReflectMut {
287 ReflectMut::Array(self)
288 }
289
290 #[inline]
291 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
292 ReflectOwned::Array(self)
293 }
294
295 #[inline]
296 fn clone_value(&self) -> Box<dyn Reflect> {
297 Box::new(self.clone_dynamic())
298 }
299
300 #[inline]
301 fn reflect_hash(&self) -> Option<u64> {
302 array_hash(self)
303 }
304
305 fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
306 array_partial_eq(self, value)
307 }
308
309 fn debug(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
310 write!(f, "DynamicArray(")?;
311 array_debug(self, f)?;
312 write!(f, ")")
313 }
314
315 #[inline]
316 fn is_dynamic(&self) -> bool {
317 true
318 }
319}
320
321impl Array for DynamicArray {
322 #[inline]
323 fn get(&self, index: usize) -> Option<&dyn Reflect> {
324 self.values.get(index).map(|value| &**value)
325 }
326
327 #[inline]
328 fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
329 self.values.get_mut(index).map(|value| &mut **value)
330 }
331
332 #[inline]
333 fn len(&self) -> usize {
334 self.values.len()
335 }
336
337 #[inline]
338 fn iter(&self) -> ArrayIter {
339 ArrayIter::new(self)
340 }
341
342 #[inline]
343 fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {
344 self.values.into_vec()
345 }
346
347 #[inline]
348 fn clone_dynamic(&self) -> DynamicArray {
349 DynamicArray {
350 represented_type: self.represented_type,
351 values: self
352 .values
353 .iter()
354 .map(|value| value.clone_value())
355 .collect(),
356 }
357 }
358}
359
360impl_type_path!((in bevy_reflect) DynamicArray);
361pub struct ArrayIter<'a> {
363 array: &'a dyn Array,
364 index: usize,
365}
366
367impl<'a> ArrayIter<'a> {
368 #[inline]
370 pub const fn new(array: &'a dyn Array) -> ArrayIter {
371 ArrayIter { array, index: 0 }
372 }
373}
374
375impl<'a> Iterator for ArrayIter<'a> {
376 type Item = &'a dyn Reflect;
377
378 #[inline]
379 fn next(&mut self) -> Option<Self::Item> {
380 let value = self.array.get(self.index);
381 self.index += value.is_some() as usize;
382 value
383 }
384
385 #[inline]
386 fn size_hint(&self) -> (usize, Option<usize>) {
387 let size = self.array.len();
388 (size, Some(size))
389 }
390}
391
392impl<'a> ExactSizeIterator for ArrayIter<'a> {}
393
394#[inline]
396pub fn array_hash<A: Array>(array: &A) -> Option<u64> {
397 let mut hasher = reflect_hasher();
398 Any::type_id(array).hash(&mut hasher);
399 array.len().hash(&mut hasher);
400 for value in array.iter() {
401 hasher.write_u64(value.reflect_hash()?);
402 }
403 Some(hasher.finish())
404}
405
406#[inline]
414pub fn array_apply<A: Array>(array: &mut A, reflect: &dyn Reflect) {
415 if let ReflectRef::Array(reflect_array) = reflect.reflect_ref() {
416 if array.len() != reflect_array.len() {
417 panic!("Attempted to apply different sized `Array` types.");
418 }
419 for (i, value) in reflect_array.iter().enumerate() {
420 let v = array.get_mut(i).unwrap();
421 v.apply(value);
422 }
423 } else {
424 panic!("Attempted to apply a non-`Array` type to an `Array` type.");
425 }
426}
427
428#[inline]
439pub fn array_try_apply<A: Array>(array: &mut A, reflect: &dyn Reflect) -> Result<(), ApplyError> {
440 if let ReflectRef::Array(reflect_array) = reflect.reflect_ref() {
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 for (i, value) in reflect_array.iter().enumerate() {
448 let v = array.get_mut(i).unwrap();
449 v.try_apply(value)?;
450 }
451 } else {
452 return Err(ApplyError::MismatchedKinds {
453 from_kind: reflect.reflect_kind(),
454 to_kind: ReflectKind::Array,
455 });
456 }
457 Ok(())
458}
459
460#[inline]
465pub fn array_partial_eq<A: Array>(array: &A, reflect: &dyn Reflect) -> Option<bool> {
466 match reflect.reflect_ref() {
467 ReflectRef::Array(reflect_array) if reflect_array.len() == array.len() => {
468 for (a, b) in array.iter().zip(reflect_array.iter()) {
469 let eq_result = a.reflect_partial_eq(b);
470 if let failed @ (Some(false) | None) = eq_result {
471 return failed;
472 }
473 }
474 }
475 _ => return Some(false),
476 }
477
478 Some(true)
479}
480
481#[inline]
499pub fn array_debug(dyn_array: &dyn Array, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
500 let mut debug = f.debug_list();
501 for item in dyn_array.iter() {
502 debug.entry(&item as &dyn Debug);
503 }
504 debug.finish()
505}
506#[cfg(test)]
507mod tests {
508 use crate::{Reflect, ReflectRef};
509 #[test]
510 fn next_index_increment() {
511 const SIZE: usize = if cfg!(debug_assertions) {
512 4
513 } else {
514 usize::MAX
516 };
517
518 let b = Box::new([(); SIZE]).into_reflect();
519
520 let ReflectRef::Array(array) = b.reflect_ref() else {
521 panic!("Not an array...");
522 };
523
524 let mut iter = array.iter();
525 iter.index = SIZE - 1;
526 assert!(iter.next().is_some());
527
528 assert!(iter.next().is_none());
530 assert!(iter.index == SIZE);
531 assert!(iter.next().is_none());
532 assert!(iter.index == SIZE);
533 }
534}