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

[reflection] impl array reflection #2383

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 244 additions & 0 deletions crates/bevy_reflect/src/array.rs
Original file line number Diff line number Diff line change
@@ -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<dyn Reflect>]>,
}

impl DynamicArray {
#[inline]
pub fn new(values: Box<[Box<dyn Reflect>]>) -> 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<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> {
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)
}
29 changes: 17 additions & 12 deletions crates/bevy_reflect/src/impls/smallvec.rs
Original file line number Diff line number Diff line change
@@ -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<T: Array + Send + Sync + 'static> List for SmallVec<T>
impl<T: smallvec::Array + Send + Sync + 'static> Array for SmallVec<T>
where
T::Item: Reflect + Clone,
{
Expand All @@ -27,6 +27,18 @@ 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: Reflect + Clone,
{
fn push(&mut self, value: Box<dyn Reflect>) {
let value = value.take::<T::Item>().unwrap_or_else(|value| {
panic!(
Expand All @@ -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<T: Array + Send + Sync + 'static> Reflect for SmallVec<T>
unsafe impl<T: smallvec::Array + Send + Sync + 'static> Reflect for SmallVec<T>
where
T::Item: Reflect + Clone,
{
Expand Down Expand Up @@ -80,7 +85,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 Down
Loading