bevy_reflect: Reflect arrays (#4701)

# Objective

> ℹ️ **Note**: This is a rebased version of #2383. A large portion of it has not been touched (only a few minor changes) so that any additional discussion may happen here. All credit should go to @NathanSWard for their work on the original PR.

- Currently reflection is not supported for arrays.
- Fixes #1213

## Solution

* Implement reflection for arrays via the `Array` trait.
* Note, `Array` is different from `List` in the way that you cannot push elements onto an array as they are statically sized.
* Now `List` is defined as a sub-trait of `Array`.

---

## Changelog

* Added the `Array` reflection trait
* Allows arrays up to length 32 to be reflected via the `Array` trait

## Migration Guide

* The `List` trait now has the `Array` supertrait. This means that `clone_dynamic` will need to specify which version to use:
  ```rust
  // Before
  let cloned = my_list.clone_dynamic();
  // After
  let cloned = List::clone_dynamic(&my_list);
  ```
* All implementers of `List` will now need to implement `Array` (this mostly involves moving the existing methods to the `Array` impl)

Co-authored-by: NathanW <nathansward@comcast.net>
Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
This commit is contained in:
MrGVSV 2022-05-13 01:13:30 +00:00
parent dfee7879c3
commit acbee7795d
10 changed files with 652 additions and 86 deletions

View file

@ -0,0 +1,300 @@
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).
///
/// Currently, this only supports arrays of up to 32 items. It can technically
/// contain more than 32, but the blanket [`GetTypeRegistration`] is only
/// implemented up to the 32 item limit due to a [limitation] on `Deserialize`.
///
/// [`GetTypeRegistration`]: crate::GetTypeRegistration
/// [limitation]: https://github.com/serde-rs/serde/issues/1937
pub trait Array: Reflect {
/// Returns a reference to the element at `index`, or `None` if out of bounds.
fn get(&self, index: usize) -> Option<&dyn Reflect>;
/// Returns a mutable reference to the element at `index`, or `None` if out of bounds.
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;
/// Returns the number of elements in the collection.
fn len(&self) -> usize;
/// Returns `true` if the collection contains no elements.
fn is_empty(&self) -> bool {
self.len() == 0
}
/// Returns an iterator over the collection.
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(),
}
}
}
/// A fixed-size list of reflected values.
///
/// This differs from [`DynamicList`] in that the size of the [`DynamicArray`]
/// is constant, whereas a [`DynamicList`] can have items added and removed.
///
/// This isn't to say that a [`DynamicArray`] is immutable— its items
/// can be mutated— just that the _number_ of items cannot change.
///
/// [`DynamicList`]: crate::DynamicList
pub struct DynamicArray {
pub(crate) name: String,
pub(crate) values: Box<[Box<dyn Reflect>]>,
}
impl DynamicArray {
#[inline]
pub fn new(values: Box<[Box<dyn Reflect>]>) -> Self {
Self {
name: String::default(),
values,
}
}
pub fn from_vec<T: Reflect>(values: Vec<T>) -> Self {
Self {
name: String::default(),
values: values
.into_iter()
.map(|field| Box::new(field) as Box<dyn Reflect>)
.collect::<Vec<_>>()
.into_boxed_slice(),
}
}
#[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
}
#[inline]
fn as_reflect(&self) -> &dyn Reflect {
self
}
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}
fn apply(&mut self, value: &dyn Reflect) {
array_apply(self, value);
}
#[inline]
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
*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<dyn Reflect> {
Box::new(self.clone_dynamic())
}
#[inline]
fn reflect_hash(&self) -> Option<u64> {
array_hash(self)
}
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
array_partial_eq(self, value)
}
fn serializable(&self) -> Option<Serializable> {
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(),
}
}
}
/// An iterator over an [`Array`].
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<Self::Item> {
let value = self.array.get(self.index);
self.index += 1;
value
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.array.len();
(size, Some(size))
}
}
impl<'a> ExactSizeIterator for ArrayIter<'a> {}
impl<'a> serde::Serialize for dyn Array {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
array_serialize(self, serializer)
}
}
impl serde::Serialize for DynamicArray {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
array_serialize(self, serializer)
}
}
/// Serializes the given [array](Array).
#[inline]
pub fn array_serialize<A: Array + ?Sized, S>(array: &A, serializer: S) -> Result<S::Ok, S::Error>
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()
}
/// Returns the `u64` hash of the given [array](Array).
#[inline]
pub fn array_hash<A: Array>(array: &A) -> Option<u64> {
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())
}
/// Applies the reflected [array](Array) data to the given [array](Array).
///
/// # Panics
///
/// * Panics if the two arrays have differing lengths.
/// * Panics if the reflected value is not a [valid array](ReflectRef::Array).
///
#[inline]
pub fn array_apply<A: Array>(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.");
}
}
/// Compares two [arrays](Array) (one concrete and one reflected) to see if they
/// are equal.
#[inline]
pub fn array_partial_eq<A: Array>(array: &A, reflect: &dyn Reflect) -> Option<bool> {
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)
}

View file

@ -1,9 +1,11 @@
use smallvec::{Array, SmallVec};
use smallvec::SmallVec;
use std::any::Any;
use crate::{serde::Serializable, FromReflect, List, ListIter, Reflect, ReflectMut, ReflectRef};
use crate::{
serde::Serializable, Array, ArrayIter, FromReflect, List, Reflect, ReflectMut, ReflectRef,
};
impl<T: Array + Send + Sync + 'static> List for SmallVec<T>
impl<T: smallvec::Array + Send + Sync + 'static> Array for SmallVec<T>
where
T::Item: FromReflect + Clone,
{
@ -27,9 +29,21 @@ where
<SmallVec<T>>::len(self)
}
fn iter(&self) -> ArrayIter {
ArrayIter {
array: self,
index: 0,
}
}
}
impl<T: smallvec::Array + Send + Sync + 'static> List for SmallVec<T>
where
T::Item: FromReflect + Clone,
{
fn push(&mut self, value: Box<dyn Reflect>) {
let value = value.take::<T::Item>().unwrap_or_else(|value| {
<T as Array>::Item::from_reflect(&*value).unwrap_or_else(|| {
<T as smallvec::Array>::Item::from_reflect(&*value).unwrap_or_else(|| {
panic!(
"Attempted to push invalid value of type {}.",
value.type_name()
@ -38,17 +52,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<T: Array + Send + Sync + 'static> Reflect for SmallVec<T>
unsafe impl<T: smallvec::Array + Send + Sync + 'static> Reflect for SmallVec<T>
where
T::Item: FromReflect + Clone,
{
@ -90,7 +97,7 @@ where
}
fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone_dynamic())
Box::new(List::clone_dynamic(self))
}
fn reflect_hash(&self) -> Option<u64> {
@ -106,7 +113,7 @@ where
}
}
impl<T: Array + Send + Sync + 'static> FromReflect for SmallVec<T>
impl<T: smallvec::Array + Send + Sync + 'static> FromReflect for SmallVec<T>
where
T::Item: FromReflect + Clone,
{
@ -114,7 +121,7 @@ where
if let ReflectRef::List(ref_list) = reflect.reflect_ref() {
let mut new_list = Self::with_capacity(ref_list.len());
for field in ref_list.iter() {
new_list.push(<T as Array>::Item::from_reflect(field)?);
new_list.push(<T as smallvec::Array>::Item::from_reflect(field)?);
}
Some(new_list)
} else {

View file

@ -1,7 +1,7 @@
use crate as bevy_reflect;
use crate::{
map_partial_eq, serde::Serializable, DynamicMap, FromReflect, FromType, GetTypeRegistration,
List, ListIter, Map, MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef,
map_partial_eq, serde::Serializable, Array, ArrayIter, DynamicMap, FromReflect, FromType,
GetTypeRegistration, List, Map, MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef,
TypeRegistration,
};
@ -63,26 +63,32 @@ impl_from_reflect_value!(
);
impl_from_reflect_value!(Duration);
impl<T: FromReflect> List for Vec<T> {
impl<T: FromReflect> Array for Vec<T> {
#[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<T: FromReflect> List for Vec<T> {
fn push(&mut self, value: Box<dyn Reflect>) {
let value = value.take::<T>().unwrap_or_else(|value| {
T::from_reflect(&*value).unwrap_or_else(|| {
@ -136,11 +142,11 @@ unsafe impl<T: FromReflect> Reflect for Vec<T> {
}
fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone_dynamic())
Box::new(List::clone_dynamic(self))
}
fn reflect_hash(&self) -> Option<u64> {
None
crate::array_hash(self)
}
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
@ -148,7 +154,7 @@ unsafe impl<T: FromReflect> Reflect for Vec<T> {
}
fn serializable(&self) -> Option<Serializable> {
None
Some(Serializable::Owned(Box::new(SerializeArrayLike(self))))
}
}
@ -306,6 +312,152 @@ impl<K: FromReflect + Eq + Hash, V: FromReflect> FromReflect for HashMap<K, V> {
}
}
impl<T: Reflect, const N: usize> 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<T: Reflect, const N: usize> Reflect for [T; N] {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}
#[inline]
fn any(&self) -> &dyn Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn as_reflect(&self) -> &dyn Reflect {
self
}
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}
#[inline]
fn apply(&mut self, value: &dyn Reflect) {
crate::array_apply(self, value);
}
#[inline]
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
*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<dyn Reflect> {
Box::new(self.clone_dynamic())
}
#[inline]
fn reflect_hash(&self) -> Option<u64> {
crate::array_hash(self)
}
#[inline]
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
crate::array_partial_eq(self, value)
}
#[inline]
fn serializable(&self) -> Option<Serializable> {
Some(Serializable::Owned(Box::new(SerializeArrayLike(self))))
}
}
impl<T: FromReflect, const N: usize> FromReflect for [T; N] {
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
if let ReflectRef::Array(ref_array) = reflect.reflect_ref() {
let mut temp_vec = Vec::with_capacity(ref_array.len());
for field in ref_array.iter() {
temp_vec.push(T::from_reflect(field)?);
}
temp_vec.try_into().ok()
} else {
None
}
}
}
// Supports dynamic serialization for types that implement `Array`.
struct SerializeArrayLike<'a>(&'a dyn Array);
impl<'a> serde::Serialize for SerializeArrayLike<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
crate::array_serialize(self.0, serializer)
}
}
// 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<T: Reflect + for<'de> Deserialize<'de>> GetTypeRegistration for [T; $N] {
fn get_type_registration() -> TypeRegistration {
let mut registration = TypeRegistration::of::<[T; $N]>();
registration.insert::<ReflectDeserialize>(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
}
// SAFE: any and any_mut both return self
unsafe impl Reflect for Cow<'static, str> {
fn type_name(&self) -> &str {

View file

@ -1,5 +1,6 @@
#![doc = include_str!("../README.md")]
mod array;
mod list;
mod map;
mod path;
@ -35,6 +36,7 @@ pub mod prelude {
};
}
pub use array::*;
pub use impls::*;
pub use list::*;
pub use map::*;
@ -242,6 +244,7 @@ mod tests {
e: Bar,
f: (i32, Vec<isize>, Bar),
g: Vec<(Baz, HashMap<usize, Bar>)>,
h: [u32; 2],
}
#[derive(Reflect, Eq, PartialEq, Clone, Debug, FromReflect)]
@ -268,6 +271,7 @@ mod tests {
e: Bar { x: 1 },
f: (1, vec![1, 2], Bar { x: 1 }),
g: vec![(Baz("string".to_string()), hash_map_baz)],
h: [2; 2],
};
let mut foo_patch = DynamicStruct::default();
@ -278,7 +282,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);
@ -315,6 +319,9 @@ mod tests {
});
foo_patch.insert("g", composite);
let array = DynamicArray::from_vec(vec![2u32, 2u32]);
foo_patch.insert("h", array);
foo.apply(&foo_patch);
let mut hash_map = HashMap::default();
@ -332,6 +339,7 @@ mod tests {
e: Bar { x: 2 },
f: (2, vec![3, 4, 5], Bar { x: 2 }),
g: vec![(Baz("new_string".to_string()), hash_map_baz.clone())],
h: [2; 2],
};
assert_eq!(foo, expected_foo);
@ -350,6 +358,7 @@ mod tests {
e: Bar { x: 2 },
f: (2, vec![3, 4, 5], Bar { x: 2 }),
g: vec![(Baz("new_string".to_string()), hash_map_baz)],
h: [2; 2],
};
assert_eq!(new_foo, expected_new_foo);
@ -367,6 +376,7 @@ mod tests {
e: Bar,
f: String,
g: (i32, Vec<isize>, Bar),
h: [u32; 2],
}
#[derive(Reflect)]
@ -385,6 +395,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();
@ -423,9 +434,13 @@ mod tests {
#[test]
fn dynamic_names() {
let list = Vec::<usize>::new();
let dyn_list = list.clone_dynamic();
let dyn_list = List::clone_dynamic(&list);
assert_eq!(dyn_list.type_name(), std::any::type_name::<Vec<usize>>());
let array = [b'0'; 4];
let dyn_array = Array::clone_dynamic(&array);
assert_eq!(dyn_array.type_name(), std::any::type_name::<[u8; 4]>());
let map = HashMap::<usize, String>::default();
let dyn_map = map.clone_dynamic();
assert_eq!(

View file

@ -1,29 +1,15 @@
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 {
/// Returns a reference to the element at `index`, or `None` if out of bounds.
fn get(&self, index: usize) -> Option<&dyn Reflect>;
/// Returns a mutable reference to the element at `index`, or `None` if out of bounds.
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;
///
/// This is a sub-trait of [`Array`] as it implements a [`push`](List::push) function, allowing
/// it's internal size to grow.
pub trait List: Reflect + Array {
/// Appends an element to the list.
fn push(&mut self, value: Box<dyn Reflect>);
/// Returns the number of elements in the list.
fn len(&self) -> usize;
/// Returns `true` if the list contains no elements.
fn is_empty(&self) -> bool {
self.len() == 0
}
/// Returns an iterator over the list.
fn iter(&self) -> ListIter;
/// Clones the list, producing a [`DynamicList`].
fn clone_dynamic(&self) -> DynamicList {
DynamicList {
@ -68,7 +54,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)
}
@ -81,6 +67,30 @@ impl List for DynamicList {
self.values.len()
}
fn iter(&self) -> ArrayIter {
ArrayIter {
array: self,
index: 0,
}
}
fn clone_dynamic(&self) -> DynamicArray {
DynamicArray {
name: self.name.clone(),
values: self
.values
.iter()
.map(|value| value.clone_value())
.collect(),
}
}
}
impl List for DynamicList {
fn push(&mut self, value: Box<dyn Reflect>) {
DynamicList::push_box(self, value);
}
fn clone_dynamic(&self) -> DynamicList {
DynamicList {
name: self.name.clone(),
@ -91,17 +101,6 @@ impl List for DynamicList {
.collect(),
}
}
fn iter(&self) -> ListIter {
ListIter {
list: self,
index: 0,
}
}
fn push(&mut self, value: Box<dyn Reflect>) {
DynamicList::push_box(self, value);
}
}
// SAFE: any and any_mut both return self
@ -153,12 +152,12 @@ unsafe impl Reflect for DynamicList {
#[inline]
fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone_dynamic())
Box::new(List::clone_dynamic(self))
}
#[inline]
fn reflect_hash(&self) -> Option<u64> {
None
crate::array_hash(self)
}
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
@ -166,28 +165,16 @@ unsafe impl Reflect for DynamicList {
}
fn serializable(&self) -> Option<Serializable> {
None
Some(Serializable::Borrowed(self))
}
}
/// An iterator over the elements of a [`List`].
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<Self::Item> {
let value = self.list.get(self.index);
self.index += 1;
value
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.list.len();
(size, Some(size))
impl serde::Serialize for DynamicList {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
crate::array_serialize(self, serializer)
}
}
@ -200,8 +187,6 @@ impl IntoIterator for DynamicList {
}
}
impl<'a> ExactSizeIterator for ListIter<'a> {}
/// Applies the elements of `b` to the corresponding elements of `a`.
///
/// If the length of `b` is greater than that of `a`, the excess elements of `b`
@ -257,6 +242,7 @@ pub fn list_partial_eq<L: List>(a: &L, b: &dyn Reflect) -> Option<bool> {
#[cfg(test)]
mod tests {
use super::DynamicList;
use std::assert_eq;
#[test]
fn test_into_iter() {

View file

@ -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;
@ -14,6 +14,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),
}
@ -29,6 +30,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),
}

View file

@ -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 = 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()
@ -282,6 +291,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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
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<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
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,
}

View file

@ -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";
}

View file

@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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()
}
}

View file

@ -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<T>
// This exposes "list" operations on your type, such as insertion. `List` is automatically
// implemented for relevant core types like Vec<T>.
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<K, V>