mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
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:
parent
dfee7879c3
commit
acbee7795d
10 changed files with 652 additions and 86 deletions
300
crates/bevy_reflect/src/array.rs
Normal file
300
crates/bevy_reflect/src/array.rs
Normal 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)
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue