Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - bevy_reflect: Reflect arrays #4701

Closed
wants to merge 15 commits into from
271 changes: 271 additions & 0 deletions crates/bevy_reflect/src/array.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
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.
MrGVSV marked this conversation as resolved.
Show resolved Hide resolved
/// This corresponds to types like `[T; N]` (arrays)
MrGVSV marked this conversation as resolved.
Show resolved Hide resolved
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(),
}
}
}

pub struct DynamicArray {
MrGVSV marked this conversation as resolved.
Show resolved Hide resolved
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(),
}
}
}

pub struct ArrayIter<'a> {
MrGVSV marked this conversation as resolved.
Show resolved Hide resolved
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)
}
}

#[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()
}

#[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())
}

#[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.");
}
}

#[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)
}
37 changes: 22 additions & 15 deletions crates/bevy_reflect/src/impls/smallvec.rs
Original file line number Diff line number Diff line change
@@ -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,
{
Expand All @@ -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()
Expand All @@ -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,
{
Expand Down Expand Up @@ -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> {
Expand All @@ -106,15 +113,15 @@ 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,
{
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
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 {
Expand Down
Loading