diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs new file mode 100644 index 0000000000000..8821043fbaebf --- /dev/null +++ b/crates/bevy_reflect/src/array.rs @@ -0,0 +1,244 @@ +use crate::{serde::Serializable, Reflect, ReflectMut, ReflectRef}; +use serde::ser::SerializeSeq; +use std::{ + any::Any, + hash::{Hash, Hasher}, +}; + +/// A static-sized array of [`Reflect`] items. +/// This corresponds to types like `[T; N]` (arrays) +pub trait Array: Reflect { + fn get(&self, index: usize) -> Option<&dyn Reflect>; + fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>; + fn len(&self) -> usize; + fn is_empty(&self) -> bool { + self.len() == 0 + } + fn iter(&self) -> ArrayIter; + fn clone_dynamic(&self) -> DynamicArray { + DynamicArray { + name: self.type_name().to_string(), + values: self.iter().map(|value| value.clone_value()).collect(), + } + } +} + +pub struct DynamicArray { + pub(crate) name: String, + pub(crate) values: Box<[Box]>, +} + +impl DynamicArray { + #[inline] + pub fn new(values: Box<[Box]>) -> Self { + Self { + name: String::default(), + values, + } + } + + #[inline] + pub fn name(&self) -> &str { + &self.name + } + + #[inline] + pub fn set_name(&mut self, name: String) { + self.name = name; + } +} + +// SAFE: any and any_mut both return self +unsafe impl Reflect for DynamicArray { + #[inline] + fn type_name(&self) -> &str { + self.name.as_str() + } + + #[inline] + fn any(&self) -> &dyn Any { + self + } + + #[inline] + fn any_mut(&mut self) -> &mut dyn Any { + self + } + + fn apply(&mut self, value: &dyn Reflect) { + array_apply(self, value); + } + + #[inline] + fn set(&mut self, value: Box) -> Result<(), Box> { + *self = value.take()?; + Ok(()) + } + + #[inline] + fn reflect_ref(&self) -> ReflectRef { + ReflectRef::Array(self) + } + + #[inline] + fn reflect_mut(&mut self) -> ReflectMut { + ReflectMut::Array(self) + } + + #[inline] + fn clone_value(&self) -> Box { + Box::new(self.clone_dynamic()) + } + + #[inline] + fn reflect_hash(&self) -> Option { + array_hash(self) + } + + fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + array_partial_eq(self, value) + } + + fn serializable(&self) -> Option { + Some(Serializable::Borrowed(self)) + } +} + +impl Array for DynamicArray { + #[inline] + fn get(&self, index: usize) -> Option<&dyn Reflect> { + self.values.get(index).map(|value| &**value) + } + + #[inline] + fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { + self.values.get_mut(index).map(|value| &mut **value) + } + + #[inline] + fn len(&self) -> usize { + self.values.len() + } + + #[inline] + fn iter(&self) -> ArrayIter { + ArrayIter { + array: self, + index: 0, + } + } + + #[inline] + fn clone_dynamic(&self) -> DynamicArray { + DynamicArray { + name: self.name.clone(), + values: self + .values + .iter() + .map(|value| value.clone_value()) + .collect(), + } + } +} + +pub struct ArrayIter<'a> { + pub(crate) array: &'a dyn Array, + pub(crate) index: usize, +} + +impl<'a> Iterator for ArrayIter<'a> { + type Item = &'a dyn Reflect; + + #[inline] + fn next(&mut self) -> Option { + let value = self.array.get(self.index); + self.index += 1; + value + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let size = self.array.len(); + (size, Some(size)) + } +} + +impl<'a> ExactSizeIterator for ArrayIter<'a> {} + +impl<'a> serde::Serialize for dyn Array { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + array_serialize(self, serializer) + } +} + +impl serde::Serialize for DynamicArray { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + array_serialize(self, serializer) + } +} + +#[inline] +pub fn array_serialize(array: &A, serializer: S) -> Result +where + S: serde::Serializer, +{ + let mut seq = serializer.serialize_seq(Some(array.len()))?; + for element in array.iter() { + let serializable = element.serializable().ok_or_else(|| { + serde::ser::Error::custom(format!( + "Type '{}' does not support `Reflect` serialization", + element.type_name() + )) + })?; + seq.serialize_element(serializable.borrow())?; + } + seq.end() +} + +#[inline] +pub fn array_hash(array: &A) -> Option { + let mut hasher = crate::ReflectHasher::default(); + std::any::Any::type_id(array).hash(&mut hasher); + array.len().hash(&mut hasher); + for value in array.iter() { + hasher.write_u64(value.reflect_hash()?) + } + Some(hasher.finish()) +} + +#[inline] +pub fn array_apply(array: &mut A, reflect: &dyn Reflect) { + if let ReflectRef::Array(reflect_array) = reflect.reflect_ref() { + if array.len() != reflect_array.len() { + panic!("Attempted to apply different sized `Array` types."); + } + for (i, value) in reflect_array.iter().enumerate() { + let v = array.get_mut(i).unwrap(); + v.apply(value); + } + } else { + panic!("Attempted to apply a non-`Array` type to an `Array` type."); + } +} + +#[inline] +pub fn array_partial_eq(array: &A, reflect: &dyn Reflect) -> Option { + match reflect.reflect_ref() { + ReflectRef::Array(reflect_array) if reflect_array.len() == array.len() => { + for (a, b) in array.iter().zip(reflect_array.iter()) { + if let Some(false) | None = a.reflect_partial_eq(b) { + return Some(false); + } + } + } + _ => return Some(false), + } + + Some(true) +} diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 942f5d3abf910..41b84ff2596e7 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -1,9 +1,9 @@ -use smallvec::{Array, SmallVec}; +use smallvec::SmallVec; use std::any::Any; -use crate::{serde::Serializable, List, ListIter, Reflect, ReflectMut, ReflectRef}; +use crate::{serde::Serializable, Array, ArrayIter, List, Reflect, ReflectMut, ReflectRef}; -impl List for SmallVec +impl Array for SmallVec where T::Item: Reflect + Clone, { @@ -27,6 +27,18 @@ where >::len(self) } + fn iter(&self) -> ArrayIter { + ArrayIter { + array: self, + index: 0, + } + } +} + +impl List for SmallVec +where + T::Item: Reflect + Clone, +{ fn push(&mut self, value: Box) { let value = value.take::().unwrap_or_else(|value| { panic!( @@ -36,17 +48,10 @@ where }); SmallVec::push(self, value); } - - fn iter(&self) -> ListIter { - ListIter { - list: self, - index: 0, - } - } } // SAFE: any and any_mut both return self -unsafe impl Reflect for SmallVec +unsafe impl Reflect for SmallVec where T::Item: Reflect + Clone, { @@ -80,7 +85,7 @@ where } fn clone_value(&self) -> Box { - Box::new(self.clone_dynamic()) + Box::new(List::clone_dynamic(self)) } fn reflect_hash(&self) -> Option { diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index bb8067fee5066..3951582204411 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -1,7 +1,8 @@ use crate as bevy_reflect; use crate::{ - map_partial_eq, serde::Serializable, DynamicMap, FromType, GetTypeRegistration, List, ListIter, - Map, MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef, TypeRegistration, + map_partial_eq, serde::Serializable, Array, ArrayIter, DynamicMap, FromType, + GetTypeRegistration, List, Map, MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef, + TypeRegistration, }; use bevy_reflect_derive::impl_reflect_value; @@ -35,26 +36,32 @@ impl_reflect_value!(HashSet Deserial impl_reflect_value!(Range Deserialize<'de> + Send + Sync + 'static>(Serialize, Deserialize)); impl_reflect_value!(Duration); -impl List for Vec { +impl Array for Vec { + #[inline] fn get(&self, index: usize) -> Option<&dyn Reflect> { <[T]>::get(self, index).map(|value| value as &dyn Reflect) } + #[inline] fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { <[T]>::get_mut(self, index).map(|value| value as &mut dyn Reflect) } + #[inline] fn len(&self) -> usize { <[T]>::len(self) } - fn iter(&self) -> ListIter { - ListIter { - list: self, + #[inline] + fn iter(&self) -> ArrayIter { + ArrayIter { + array: self, index: 0, } } +} +impl List for Vec { fn push(&mut self, value: Box) { let value = value.take::().unwrap_or_else(|value| { panic!( @@ -98,11 +105,11 @@ unsafe impl Reflect for Vec { } fn clone_value(&self) -> Box { - Box::new(self.clone_dynamic()) + Box::new(List::clone_dynamic(self)) } fn reflect_hash(&self) -> Option { - None + crate::array_hash(self) } fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { @@ -110,7 +117,7 @@ unsafe impl Reflect for Vec { } fn serializable(&self) -> Option { - None + Some(Serializable::Owned(Box::new(SerializeArrayLike(self)))) } } @@ -298,3 +305,125 @@ impl GetTypeRegistration for Cow<'static, str> { registration } } + +impl Array for [T; N] { + #[inline] + fn get(&self, index: usize) -> Option<&dyn Reflect> { + <[T]>::get(self, index).map(|value| value as &dyn Reflect) + } + + #[inline] + fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { + <[T]>::get_mut(self, index).map(|value| value as &mut dyn Reflect) + } + + #[inline] + fn len(&self) -> usize { + N + } + + #[inline] + fn iter(&self) -> ArrayIter { + ArrayIter { + array: self, + index: 0, + } + } +} + +// SAFE: any and any_mut both return self +unsafe impl Reflect for [T; N] { + #[inline] + fn type_name(&self) -> &str { + std::any::type_name::() + } + + #[inline] + fn any(&self) -> &dyn Any { + self + } + + #[inline] + fn any_mut(&mut self) -> &mut dyn Any { + self + } + + #[inline] + fn apply(&mut self, value: &dyn Reflect) { + crate::array_apply(self, value); + } + + #[inline] + fn set(&mut self, value: Box) -> Result<(), Box> { + *self = value.take()?; + Ok(()) + } + + #[inline] + fn reflect_ref(&self) -> ReflectRef { + ReflectRef::Array(self) + } + + #[inline] + fn reflect_mut(&mut self) -> ReflectMut { + ReflectMut::Array(self) + } + + #[inline] + fn clone_value(&self) -> Box { + Box::new(self.clone_dynamic()) + } + + #[inline] + fn reflect_hash(&self) -> Option { + crate::array_hash(self) + } + + #[inline] + fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + crate::array_partial_eq(self, value) + } + + #[inline] + fn serializable(&self) -> Option { + Some(Serializable::Owned(Box::new(SerializeArrayLike(self)))) + } +} + +// TODO: +// `FromType::from_type` requires `Deserialize<'de>` to be implemented for `T`. +// Currently serde only supports `Deserialize<'de>` for arrays up to size 32. +// This can be changed to use const generics once serde utilizes const generics for arrays. +// Tracking issue: https://github.com/serde-rs/serde/issues/1937 +macro_rules! impl_array_get_type_registration { + ($($N:expr)+) => { + $( + impl Deserialize<'de>> GetTypeRegistration for [T; $N] { + fn get_type_registration() -> TypeRegistration { + let mut registration = TypeRegistration::of::<[T; $N]>(); + registration.insert::(FromType::<[T; $N]>::from_type()); + registration + } + } + )+ + }; +} + +impl_array_get_type_registration! { + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 +} + +// Supports dynamic serialization for types that implement `Array`. +struct SerializeArrayLike<'a>(&'a dyn Array); + +impl<'a> serde::Serialize for SerializeArrayLike<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + crate::array_serialize(self.0, serializer) + } +} diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 7726ce7ee4e76..56ecbed1177ad 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1,3 +1,4 @@ +mod array; mod list; mod map; mod path; @@ -30,6 +31,7 @@ pub mod prelude { }; } +pub use array::*; pub use impls::*; pub use list::*; pub use map::*; @@ -204,6 +206,7 @@ mod tests { d: HashMap, e: Bar, f: (i32, Vec, Bar), + h: [u32; 2], } #[derive(Reflect, Eq, PartialEq, Debug)] @@ -222,6 +225,7 @@ mod tests { d: hash_map, e: Bar { x: 1 }, f: (1, vec![1, 2], Bar { x: 1 }), + h: [2; 2], }; let mut foo_patch = DynamicStruct::default(); @@ -232,7 +236,7 @@ mod tests { list.push(3isize); list.push(4isize); list.push(5isize); - foo_patch.insert("c", list.clone_dynamic()); + foo_patch.insert("c", List::clone_dynamic(&list)); let mut map = DynamicMap::default(); map.insert(2usize, 3i8); @@ -260,6 +264,7 @@ mod tests { d: hash_map, e: Bar { x: 2 }, f: (2, vec![3, 4, 5], Bar { x: 2 }), + h: [2; 2], }; assert_eq!(foo, expected_foo); @@ -277,6 +282,7 @@ mod tests { e: Bar, f: String, g: (i32, Vec, Bar), + h: [u32; 2], } #[derive(Reflect)] @@ -295,6 +301,7 @@ mod tests { e: Bar { x: 1 }, f: "hi".to_string(), g: (1, vec![1, 2], Bar { x: 1 }), + h: [2; 2], }; let mut registry = TypeRegistry::default(); @@ -333,9 +340,13 @@ mod tests { #[test] fn dynamic_names() { let list = Vec::::new(); - let dyn_list = list.clone_dynamic(); + let dyn_list = List::clone_dynamic(&list); assert_eq!(dyn_list.type_name(), std::any::type_name::>()); + let array = [b'0'; 4]; + let dyn_array = array.clone_dynamic(); + assert_eq!(dyn_array.type_name(), std::any::type_name::<[u8; 4]>()); + let map = HashMap::::default(); let dyn_map = map.clone_dynamic(); assert_eq!( diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 2ecb8f52b2c82..66aa8cc2961b0 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -1,17 +1,12 @@ use std::any::Any; -use crate::{serde::Serializable, Reflect, ReflectMut, ReflectRef}; +use crate::{serde::Serializable, Array, ArrayIter, DynamicArray, Reflect, ReflectMut, ReflectRef}; /// An ordered, mutable list of [Reflect] items. This corresponds to types like [std::vec::Vec]. -pub trait List: Reflect { - fn get(&self, index: usize) -> Option<&dyn Reflect>; - fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>; +/// This is a sub-trait of [`Array`] as it implements a `push` function, allowing it's internal +/// size to grow. +pub trait List: Array { fn push(&mut self, value: Box); - fn len(&self) -> usize; - fn is_empty(&self) -> bool { - self.len() == 0 - } - fn iter(&self) -> ListIter; fn clone_dynamic(&self) -> DynamicList { DynamicList { name: self.type_name().to_string(), @@ -44,7 +39,7 @@ impl DynamicList { } } -impl List for DynamicList { +impl Array for DynamicList { fn get(&self, index: usize) -> Option<&dyn Reflect> { self.values.get(index).map(|value| &**value) } @@ -57,8 +52,15 @@ impl List for DynamicList { self.values.len() } - fn clone_dynamic(&self) -> DynamicList { - DynamicList { + fn iter(&self) -> ArrayIter { + ArrayIter { + array: self, + index: 0, + } + } + + fn clone_dynamic(&self) -> DynamicArray { + DynamicArray { name: self.name.clone(), values: self .values @@ -67,17 +69,23 @@ impl List for DynamicList { .collect(), } } +} - fn iter(&self) -> ListIter { - ListIter { - list: self, - index: 0, - } - } - +impl List for DynamicList { fn push(&mut self, value: Box) { DynamicList::push_box(self, value); } + + fn clone_dynamic(&self) -> DynamicList { + DynamicList { + name: self.name.clone(), + values: self + .values + .iter() + .map(|value| value.clone_value()) + .collect(), + } + } } // SAFE: any and any_mut both return self @@ -119,12 +127,12 @@ unsafe impl Reflect for DynamicList { #[inline] fn clone_value(&self) -> Box { - Box::new(self.clone_dynamic()) + Box::new(List::clone_dynamic(self)) } #[inline] fn reflect_hash(&self) -> Option { - None + crate::array_hash(self) } fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { @@ -132,32 +140,19 @@ unsafe impl Reflect for DynamicList { } fn serializable(&self) -> Option { - None + Some(Serializable::Borrowed(self)) } } -pub struct ListIter<'a> { - pub(crate) list: &'a dyn List, - pub(crate) index: usize, -} - -impl<'a> Iterator for ListIter<'a> { - type Item = &'a dyn Reflect; - - fn next(&mut self) -> Option { - let value = self.list.get(self.index); - self.index += 1; - value - } - - fn size_hint(&self) -> (usize, Option) { - let size = self.list.len(); - (size, Some(size)) +impl serde::Serialize for DynamicList { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + crate::array_serialize(self, serializer) } } -impl<'a> ExactSizeIterator for ListIter<'a> {} - #[inline] pub fn list_apply(a: &mut L, b: &dyn Reflect) { if let ReflectRef::List(list_value) = b.reflect_ref() { diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index df7749599ba2f..da24abf6f7e5d 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -1,4 +1,4 @@ -use crate::{serde::Serializable, List, Map, Struct, Tuple, TupleStruct}; +use crate::{serde::Serializable, Array, List, Map, Struct, Tuple, TupleStruct}; use std::{any::Any, fmt::Debug}; pub use bevy_utils::AHasher as ReflectHasher; @@ -8,6 +8,7 @@ pub enum ReflectRef<'a> { TupleStruct(&'a dyn TupleStruct), Tuple(&'a dyn Tuple), List(&'a dyn List), + Array(&'a dyn Array), Map(&'a dyn Map), Value(&'a dyn Reflect), } @@ -17,6 +18,7 @@ pub enum ReflectMut<'a> { TupleStruct(&'a mut dyn TupleStruct), Tuple(&'a mut dyn Tuple), List(&'a mut dyn List), + Array(&'a mut dyn Array), Map(&'a mut dyn Map), Value(&'a mut dyn Reflect), } diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index b7bf5ec9b4858..721e96ccb301b 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -1,6 +1,6 @@ use crate::{ - serde::type_fields, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, DynamicTupleStruct, - Reflect, ReflectDeserialize, TypeRegistry, + serde::type_fields, DynamicArray, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, + DynamicTupleStruct, Reflect, ReflectDeserialize, TypeRegistry, }; use erased_serde::Deserializer; use serde::de::{self, DeserializeSeed, MapAccess, SeqAccess, Visitor}; @@ -194,6 +194,15 @@ impl<'a, 'de> Visitor<'de> for ReflectVisitor<'a> { })?; return Ok(Box::new(list)); } + type_fields::ARRAY => { + let _ = type_name + .take() + .ok_or_else(|| de::Error::missing_field(type_fields::TYPE))?; + let array = map.next_value_seed(ArrayDeserializer { + registry: self.registry, + })?; + return Ok(Box::new(array)); + } type_fields::VALUE => { let type_name = type_name .take() @@ -279,6 +288,49 @@ impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { } } +struct ArrayDeserializer<'a> { + registry: &'a TypeRegistry, +} + +impl<'a, 'de> DeserializeSeed<'de> for ArrayDeserializer<'a> { + type Value = DynamicArray; + + fn deserialize(self, deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_seq(ArrayVisitor { + registry: self.registry, + }) + } +} + +struct ArrayVisitor<'a> { + registry: &'a TypeRegistry, +} + +impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> { + type Value = DynamicArray; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("array value") + } + + fn visit_seq(self, mut seq: V) -> Result + where + V: SeqAccess<'de>, + { + let mut vec = Vec::with_capacity(seq.size_hint().unwrap_or_default()); + while let Some(value) = seq.next_element_seed(ReflectDeserializer { + registry: self.registry, + })? { + vec.push(value); + } + + Ok(DynamicArray::new(Box::from(vec))) + } +} + struct MapDeserializer<'a> { registry: &'a TypeRegistry, } diff --git a/crates/bevy_reflect/src/serde/mod.rs b/crates/bevy_reflect/src/serde/mod.rs index 9354d864261ef..5e664112a8860 100644 --- a/crates/bevy_reflect/src/serde/mod.rs +++ b/crates/bevy_reflect/src/serde/mod.rs @@ -11,5 +11,6 @@ pub(crate) mod type_fields { pub const TUPLE_STRUCT: &str = "tuple_struct"; pub const TUPLE: &str = "tuple"; pub const LIST: &str = "list"; + pub const ARRAY: &str = "array"; pub const VALUE: &str = "value"; } diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index a865bd13b438b..38993cbac35a6 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -1,5 +1,6 @@ use crate::{ - serde::type_fields, List, Map, Reflect, ReflectRef, Struct, Tuple, TupleStruct, TypeRegistry, + serde::type_fields, Array, List, Map, Reflect, ReflectRef, Struct, Tuple, TupleStruct, + TypeRegistry, }; use serde::{ ser::{SerializeMap, SerializeSeq}, @@ -67,6 +68,11 @@ impl<'a> Serialize for ReflectSerializer<'a> { registry: self.registry, } .serialize(serializer), + ReflectRef::Array(value) => ArraySerializer { + array: value, + registry: self.registry, + } + .serialize(serializer), ReflectRef::Map(value) => MapSerializer { map: value, registry: self.registry, @@ -313,3 +319,44 @@ impl<'a> Serialize for ListValueSerializer<'a> { state.end() } } + +pub struct ArraySerializer<'a> { + pub array: &'a dyn Array, + pub registry: &'a TypeRegistry, +} + +impl<'a> Serialize for ArraySerializer<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut state = serializer.serialize_map(Some(2))?; + state.serialize_entry(type_fields::TYPE, self.array.type_name())?; + state.serialize_entry( + type_fields::ARRAY, + &ArrayValueSerializer { + array: self.array, + registry: self.registry, + }, + )?; + state.end() + } +} + +pub struct ArrayValueSerializer<'a> { + pub array: &'a dyn Array, + pub registry: &'a TypeRegistry, +} + +impl<'a> Serialize for ArrayValueSerializer<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut state = serializer.serialize_seq(Some(self.array.len()))?; + for value in self.array.iter() { + state.serialize_element(&ReflectSerializer::new(value, self.registry))?; + } + state.end() + } +} diff --git a/examples/reflection/reflection_types.rs b/examples/reflection/reflection_types.rs index 4ecf800fb28bb..94259f4d962e8 100644 --- a/examples/reflection/reflection_types.rs +++ b/examples/reflection/reflection_types.rs @@ -80,9 +80,13 @@ fn setup() { // arity 12 or less. ReflectRef::Tuple(_) => {} // `List` is a special trait that can be manually implemented (instead of deriving Reflect). - // This exposes "list" operations on your type, such as indexing and insertion. List - // is automatically implemented for relevant core types like Vec + // This exposes "list" operations on your type, such as insertion. List is automatically + // implemented for relevant core types like Vec ReflectRef::List(_) => {} + // `Array` is a special trait that can be manually implemented (instead of deriving Reflect). + // This exposes "array" operations on your type, such as indexing. `Array` + // is automatically implemented for relevant core types like [T; N] + ReflectRef::Array(_) => {} // `Map` is a special trait that can be manually implemented (instead of deriving Reflect). // This exposes "map" operations on your type, such as getting / inserting by key. // Map is automatically implemented for relevant core types like HashMap