Implement Reflect for tuples up to length 12 (#1218)
Add Reflect impls for tuples up to length 12
This commit is contained in:
parent
9bce8712b5
commit
5e7456115a
@ -3,6 +3,7 @@ mod map;
|
|||||||
mod path;
|
mod path;
|
||||||
mod reflect;
|
mod reflect;
|
||||||
mod struct_trait;
|
mod struct_trait;
|
||||||
|
mod tuple;
|
||||||
mod tuple_struct;
|
mod tuple_struct;
|
||||||
mod type_registry;
|
mod type_registry;
|
||||||
mod type_uuid;
|
mod type_uuid;
|
||||||
@ -46,6 +47,7 @@ pub use map::*;
|
|||||||
pub use path::*;
|
pub use path::*;
|
||||||
pub use reflect::*;
|
pub use reflect::*;
|
||||||
pub use struct_trait::*;
|
pub use struct_trait::*;
|
||||||
|
pub use tuple::*;
|
||||||
pub use tuple_struct::*;
|
pub use tuple_struct::*;
|
||||||
pub use type_registry::*;
|
pub use type_registry::*;
|
||||||
pub use type_uuid::*;
|
pub use type_uuid::*;
|
||||||
@ -208,6 +210,7 @@ mod tests {
|
|||||||
c: Vec<isize>,
|
c: Vec<isize>,
|
||||||
d: HashMap<usize, i8>,
|
d: HashMap<usize, i8>,
|
||||||
e: Bar,
|
e: Bar,
|
||||||
|
f: (i32, Vec<isize>, Bar),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Reflect, Eq, PartialEq, Debug)]
|
#[derive(Reflect, Eq, PartialEq, Debug)]
|
||||||
@ -224,6 +227,7 @@ mod tests {
|
|||||||
c: vec![1, 2],
|
c: vec![1, 2],
|
||||||
d: hash_map,
|
d: hash_map,
|
||||||
e: Bar { x: 1 },
|
e: Bar { x: 1 },
|
||||||
|
f: (1, vec![1, 2], Bar { x: 1 }),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut foo_patch = DynamicStruct::default();
|
let mut foo_patch = DynamicStruct::default();
|
||||||
@ -234,7 +238,7 @@ mod tests {
|
|||||||
list.push(3isize);
|
list.push(3isize);
|
||||||
list.push(4isize);
|
list.push(4isize);
|
||||||
list.push(5isize);
|
list.push(5isize);
|
||||||
foo_patch.insert("c", list);
|
foo_patch.insert("c", list.clone_dynamic());
|
||||||
|
|
||||||
let mut map = DynamicMap::default();
|
let mut map = DynamicMap::default();
|
||||||
map.insert(2usize, 3i8);
|
map.insert(2usize, 3i8);
|
||||||
@ -242,7 +246,13 @@ mod tests {
|
|||||||
|
|
||||||
let mut bar_patch = DynamicStruct::default();
|
let mut bar_patch = DynamicStruct::default();
|
||||||
bar_patch.insert("x", 2u32);
|
bar_patch.insert("x", 2u32);
|
||||||
foo_patch.insert("e", bar_patch);
|
foo_patch.insert("e", bar_patch.clone_dynamic());
|
||||||
|
|
||||||
|
let mut tuple = DynamicTuple::default();
|
||||||
|
tuple.insert(2i32);
|
||||||
|
tuple.insert(list);
|
||||||
|
tuple.insert(bar_patch);
|
||||||
|
foo_patch.insert("f", tuple);
|
||||||
|
|
||||||
foo.apply(&foo_patch);
|
foo.apply(&foo_patch);
|
||||||
|
|
||||||
@ -255,6 +265,7 @@ mod tests {
|
|||||||
c: vec![3, 4, 5],
|
c: vec![3, 4, 5],
|
||||||
d: hash_map,
|
d: hash_map,
|
||||||
e: Bar { x: 2 },
|
e: Bar { x: 2 },
|
||||||
|
f: (2, vec![3, 4, 5], Bar { x: 2 }),
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(foo, expected_foo);
|
assert_eq!(foo, expected_foo);
|
||||||
@ -271,6 +282,7 @@ mod tests {
|
|||||||
d: HashMap<usize, i8>,
|
d: HashMap<usize, i8>,
|
||||||
e: Bar,
|
e: Bar,
|
||||||
f: String,
|
f: String,
|
||||||
|
g: (i32, Vec<isize>, Bar),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Reflect)]
|
#[derive(Reflect)]
|
||||||
@ -288,6 +300,7 @@ mod tests {
|
|||||||
d: hash_map,
|
d: hash_map,
|
||||||
e: Bar { x: 1 },
|
e: Bar { x: 1 },
|
||||||
f: "hi".to_string(),
|
f: "hi".to_string(),
|
||||||
|
g: (1, vec![1, 2], Bar { x: 1 }),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut registry = TypeRegistry::default();
|
let mut registry = TypeRegistry::default();
|
||||||
@ -297,6 +310,7 @@ mod tests {
|
|||||||
registry.register::<Bar>();
|
registry.register::<Bar>();
|
||||||
registry.register::<String>();
|
registry.register::<String>();
|
||||||
registry.register::<i8>();
|
registry.register::<i8>();
|
||||||
|
registry.register::<i32>();
|
||||||
|
|
||||||
let serializer = ReflectSerializer::new(&foo, ®istry);
|
let serializer = ReflectSerializer::new(&foo, ®istry);
|
||||||
let serialized = to_string_pretty(&serializer, PrettyConfig::default()).unwrap();
|
let serialized = to_string_pretty(&serializer, PrettyConfig::default()).unwrap();
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::{serde::Serializable, List, Map, Struct, TupleStruct};
|
use crate::{serde::Serializable, List, Map, Struct, Tuple, TupleStruct};
|
||||||
use std::{any::Any, fmt::Debug};
|
use std::{any::Any, fmt::Debug};
|
||||||
|
|
||||||
pub use bevy_utils::AHasher as ReflectHasher;
|
pub use bevy_utils::AHasher as ReflectHasher;
|
||||||
@ -6,6 +6,7 @@ pub use bevy_utils::AHasher as ReflectHasher;
|
|||||||
pub enum ReflectRef<'a> {
|
pub enum ReflectRef<'a> {
|
||||||
Struct(&'a dyn Struct),
|
Struct(&'a dyn Struct),
|
||||||
TupleStruct(&'a dyn TupleStruct),
|
TupleStruct(&'a dyn TupleStruct),
|
||||||
|
Tuple(&'a dyn Tuple),
|
||||||
List(&'a dyn List),
|
List(&'a dyn List),
|
||||||
Map(&'a dyn Map),
|
Map(&'a dyn Map),
|
||||||
Value(&'a dyn Reflect),
|
Value(&'a dyn Reflect),
|
||||||
@ -14,6 +15,7 @@ pub enum ReflectRef<'a> {
|
|||||||
pub enum ReflectMut<'a> {
|
pub enum ReflectMut<'a> {
|
||||||
Struct(&'a mut dyn Struct),
|
Struct(&'a mut dyn Struct),
|
||||||
TupleStruct(&'a mut dyn TupleStruct),
|
TupleStruct(&'a mut dyn TupleStruct),
|
||||||
|
Tuple(&'a dyn Tuple),
|
||||||
List(&'a mut dyn List),
|
List(&'a mut dyn List),
|
||||||
Map(&'a mut dyn Map),
|
Map(&'a mut dyn Map),
|
||||||
Value(&'a mut dyn Reflect),
|
Value(&'a mut dyn Reflect),
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
serde::type_fields, DynamicList, DynamicMap, DynamicStruct, DynamicTupleStruct, Reflect,
|
serde::type_fields, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, DynamicTupleStruct,
|
||||||
ReflectDeserialize, TypeRegistry,
|
Reflect, ReflectDeserialize, TypeRegistry,
|
||||||
};
|
};
|
||||||
use erased_serde::Deserializer;
|
use erased_serde::Deserializer;
|
||||||
use serde::de::{self, DeserializeSeed, MapAccess, SeqAccess, Visitor};
|
use serde::de::{self, DeserializeSeed, MapAccess, SeqAccess, Visitor};
|
||||||
@ -176,6 +176,15 @@ impl<'a, 'de> Visitor<'de> for ReflectVisitor<'a> {
|
|||||||
tuple_struct.set_name(type_name);
|
tuple_struct.set_name(type_name);
|
||||||
return Ok(Box::new(tuple_struct));
|
return Ok(Box::new(tuple_struct));
|
||||||
}
|
}
|
||||||
|
type_fields::TUPLE => {
|
||||||
|
let _type_name = type_name
|
||||||
|
.take()
|
||||||
|
.ok_or_else(|| de::Error::missing_field(type_fields::TYPE))?;
|
||||||
|
let tuple = map.next_value_seed(TupleDeserializer {
|
||||||
|
registry: self.registry,
|
||||||
|
})?;
|
||||||
|
return Ok(Box::new(tuple));
|
||||||
|
}
|
||||||
type_fields::LIST => {
|
type_fields::LIST => {
|
||||||
let _type_name = type_name
|
let _type_name = type_name
|
||||||
.take()
|
.take()
|
||||||
@ -401,3 +410,45 @@ impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> {
|
|||||||
Ok(tuple_struct)
|
Ok(tuple_struct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TupleDeserializer<'a> {
|
||||||
|
registry: &'a TypeRegistry,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'de> DeserializeSeed<'de> for TupleDeserializer<'a> {
|
||||||
|
type Value = DynamicTuple;
|
||||||
|
|
||||||
|
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserializer.deserialize_seq(TupleVisitor {
|
||||||
|
registry: self.registry,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TupleVisitor<'a> {
|
||||||
|
registry: &'a TypeRegistry,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> {
|
||||||
|
type Value = DynamicTuple;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
formatter.write_str("tuple value")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
|
||||||
|
where
|
||||||
|
V: SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut tuple = DynamicTuple::default();
|
||||||
|
while let Some(value) = seq.next_element_seed(ReflectDeserializer {
|
||||||
|
registry: self.registry,
|
||||||
|
})? {
|
||||||
|
tuple.insert_boxed(value);
|
||||||
|
}
|
||||||
|
Ok(tuple)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ pub(crate) mod type_fields {
|
|||||||
pub const MAP: &str = "map";
|
pub const MAP: &str = "map";
|
||||||
pub const STRUCT: &str = "struct";
|
pub const STRUCT: &str = "struct";
|
||||||
pub const TUPLE_STRUCT: &str = "tuple_struct";
|
pub const TUPLE_STRUCT: &str = "tuple_struct";
|
||||||
|
pub const TUPLE: &str = "tuple";
|
||||||
pub const LIST: &str = "list";
|
pub const LIST: &str = "list";
|
||||||
pub const VALUE: &str = "value";
|
pub const VALUE: &str = "value";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
serde::type_fields, List, Map, Reflect, ReflectRef, Struct, TupleStruct, TypeRegistry,
|
serde::type_fields, List, Map, Reflect, ReflectRef, Struct, Tuple, TupleStruct, TypeRegistry,
|
||||||
};
|
};
|
||||||
use serde::{
|
use serde::{
|
||||||
ser::{SerializeMap, SerializeSeq},
|
ser::{SerializeMap, SerializeSeq},
|
||||||
@ -57,6 +57,11 @@ impl<'a> Serialize for ReflectSerializer<'a> {
|
|||||||
registry: self.registry,
|
registry: self.registry,
|
||||||
}
|
}
|
||||||
.serialize(serializer),
|
.serialize(serializer),
|
||||||
|
ReflectRef::Tuple(value) => TupleSerializer {
|
||||||
|
tuple: value,
|
||||||
|
registry: self.registry,
|
||||||
|
}
|
||||||
|
.serialize(serializer),
|
||||||
ReflectRef::List(value) => ListSerializer {
|
ReflectRef::List(value) => ListSerializer {
|
||||||
list: value,
|
list: value,
|
||||||
registry: self.registry,
|
registry: self.registry,
|
||||||
@ -181,6 +186,48 @@ impl<'a> Serialize for TupleStructValueSerializer<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct TupleSerializer<'a> {
|
||||||
|
pub tuple: &'a dyn Tuple,
|
||||||
|
pub registry: &'a TypeRegistry,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Serialize for TupleSerializer<'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.tuple.type_name())?;
|
||||||
|
state.serialize_entry(
|
||||||
|
type_fields::TUPLE,
|
||||||
|
&TupleValueSerializer {
|
||||||
|
tuple: self.tuple,
|
||||||
|
registry: self.registry,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
state.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TupleValueSerializer<'a> {
|
||||||
|
pub tuple: &'a dyn Tuple,
|
||||||
|
pub registry: &'a TypeRegistry,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Serialize for TupleValueSerializer<'a> {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
let mut state = serializer.serialize_seq(Some(self.tuple.field_len()))?;
|
||||||
|
for value in self.tuple.iter_fields() {
|
||||||
|
state.serialize_element(&ReflectSerializer::new(value, self.registry))?;
|
||||||
|
}
|
||||||
|
state.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MapSerializer<'a> {
|
pub struct MapSerializer<'a> {
|
||||||
pub map: &'a dyn Map,
|
pub map: &'a dyn Map,
|
||||||
pub registry: &'a TypeRegistry,
|
pub registry: &'a TypeRegistry,
|
||||||
|
|||||||
310
crates/bevy_reflect/src/tuple.rs
Normal file
310
crates/bevy_reflect/src/tuple.rs
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
use std::any::Any;
|
||||||
|
|
||||||
|
use crate::{serde::Serializable, Reflect, ReflectMut, ReflectRef};
|
||||||
|
|
||||||
|
pub trait Tuple: Reflect {
|
||||||
|
fn field(&self, index: usize) -> Option<&dyn Reflect>;
|
||||||
|
fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;
|
||||||
|
fn field_len(&self) -> usize;
|
||||||
|
fn iter_fields(&self) -> TupleFieldIter;
|
||||||
|
fn clone_dynamic(&self) -> DynamicTuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TupleFieldIter<'a> {
|
||||||
|
pub(crate) tuple: &'a dyn Tuple,
|
||||||
|
pub(crate) index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TupleFieldIter<'a> {
|
||||||
|
pub fn new(value: &'a dyn Tuple) -> Self {
|
||||||
|
TupleFieldIter {
|
||||||
|
tuple: value,
|
||||||
|
index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for TupleFieldIter<'a> {
|
||||||
|
type Item = &'a dyn Reflect;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let value = self.tuple.field(self.index);
|
||||||
|
self.index += 1;
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait GetTupleField {
|
||||||
|
fn get_field<T: Reflect>(&self, index: usize) -> Option<&T>;
|
||||||
|
fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: Tuple> GetTupleField for S {
|
||||||
|
fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
|
||||||
|
self.field(index)
|
||||||
|
.and_then(|value| value.downcast_ref::<T>())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
|
||||||
|
self.field_mut(index)
|
||||||
|
.and_then(|value| value.downcast_mut::<T>())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetTupleField for dyn Tuple {
|
||||||
|
fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
|
||||||
|
self.field(index)
|
||||||
|
.and_then(|value| value.downcast_ref::<T>())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
|
||||||
|
self.field_mut(index)
|
||||||
|
.and_then(|value| value.downcast_mut::<T>())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct DynamicTuple {
|
||||||
|
pub(crate) fields: Vec<Box<dyn Reflect>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DynamicTuple {
|
||||||
|
pub fn insert_boxed(&mut self, value: Box<dyn Reflect>) {
|
||||||
|
self.fields.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert<T: Reflect>(&mut self, value: T) {
|
||||||
|
self.insert_boxed(Box::new(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tuple for DynamicTuple {
|
||||||
|
#[inline]
|
||||||
|
fn field(&self, index: usize) -> Option<&dyn Reflect> {
|
||||||
|
self.fields.get(index).map(|field| &**field)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
|
||||||
|
self.fields.get_mut(index).map(|field| &mut **field)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn field_len(&self) -> usize {
|
||||||
|
self.fields.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn iter_fields(&self) -> TupleFieldIter {
|
||||||
|
TupleFieldIter {
|
||||||
|
tuple: self,
|
||||||
|
index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn clone_dynamic(&self) -> DynamicTuple {
|
||||||
|
DynamicTuple {
|
||||||
|
fields: self
|
||||||
|
.fields
|
||||||
|
.iter()
|
||||||
|
.map(|value| value.clone_value())
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Reflect for DynamicTuple {
|
||||||
|
#[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 clone_value(&self) -> Box<dyn Reflect> {
|
||||||
|
Box::new(self.clone_dynamic())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn reflect_ref(&self) -> ReflectRef {
|
||||||
|
ReflectRef::Tuple(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn reflect_mut(&mut self) -> ReflectMut {
|
||||||
|
ReflectMut::Tuple(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(&mut self, value: &dyn Reflect) {
|
||||||
|
tuple_apply(self, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
||||||
|
*self = value.take()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reflect_hash(&self) -> Option<u64> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
||||||
|
tuple_partial_eq(self, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serializable(&self) -> Option<Serializable> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn tuple_apply<T: Tuple>(a: &mut T, b: &dyn Reflect) {
|
||||||
|
if let ReflectRef::Tuple(tuple) = b.reflect_ref() {
|
||||||
|
for (i, value) in tuple.iter_fields().enumerate() {
|
||||||
|
if let Some(v) = a.field_mut(i) {
|
||||||
|
v.apply(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("Attempted to apply non-Tuple type to Tuple type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn tuple_partial_eq<T: Tuple>(a: &T, b: &dyn Reflect) -> Option<bool> {
|
||||||
|
let b = if let ReflectRef::Tuple(tuple) = b.reflect_ref() {
|
||||||
|
tuple
|
||||||
|
} else {
|
||||||
|
return Some(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
if a.field_len() != b.field_len() {
|
||||||
|
return Some(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a_field, b_field) in a.iter_fields().zip(b.iter_fields()) {
|
||||||
|
match a_field.reflect_partial_eq(b_field) {
|
||||||
|
Some(false) | None => return Some(false),
|
||||||
|
Some(true) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_reflect_tuple {
|
||||||
|
{$($index:tt : $name:tt),*} => {
|
||||||
|
impl<$($name: Reflect),*> Tuple for ($($name,)*) {
|
||||||
|
#[inline]
|
||||||
|
fn field(&self, index: usize) -> Option<&dyn Reflect> {
|
||||||
|
match index {
|
||||||
|
$($index => Some(&self.$index as &dyn Reflect),)*
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
|
||||||
|
match index {
|
||||||
|
$($index => Some(&mut self.$index as &mut dyn Reflect),)*
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn field_len(&self) -> usize {
|
||||||
|
let indices: &[usize] = &[$($index as usize),*];
|
||||||
|
indices.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn iter_fields(&self) -> TupleFieldIter {
|
||||||
|
TupleFieldIter {
|
||||||
|
tuple: self,
|
||||||
|
index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn clone_dynamic(&self) -> DynamicTuple {
|
||||||
|
DynamicTuple {
|
||||||
|
fields: self
|
||||||
|
.iter_fields()
|
||||||
|
.map(|value| value.clone_value())
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<$($name: Reflect),*> Reflect for ($($name,)*) {
|
||||||
|
fn type_name(&self) -> &str {
|
||||||
|
std::any::type_name::<Self>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn any_mut(&mut self) -> &mut dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(&mut self, value: &dyn Reflect) {
|
||||||
|
crate::tuple_apply(self, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
||||||
|
*self = value.take()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reflect_ref(&self) -> ReflectRef {
|
||||||
|
ReflectRef::Tuple(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reflect_mut(&mut self) -> ReflectMut {
|
||||||
|
ReflectMut::Tuple(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_value(&self) -> Box<dyn Reflect> {
|
||||||
|
Box::new(self.clone_dynamic())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reflect_hash(&self) -> Option<u64> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
||||||
|
crate::tuple_partial_eq(self, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serializable(&self) -> Option<Serializable> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_reflect_tuple! {}
|
||||||
|
impl_reflect_tuple! {0: A}
|
||||||
|
impl_reflect_tuple! {0: A, 1: B}
|
||||||
|
impl_reflect_tuple! {0: A, 1: B, 2: C}
|
||||||
|
impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D}
|
||||||
|
impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E}
|
||||||
|
impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F}
|
||||||
|
impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G}
|
||||||
|
impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H}
|
||||||
|
impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I}
|
||||||
|
impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J}
|
||||||
|
impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K}
|
||||||
|
impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K, 11: L}
|
||||||
@ -71,6 +71,10 @@ fn setup() {
|
|||||||
// `TupleStruct` is a trait automatically implemented for tuple structs that derive Reflect. This trait allows you
|
// `TupleStruct` is a trait automatically implemented for tuple structs that derive Reflect. This trait allows you
|
||||||
// to interact with fields via their indices
|
// to interact with fields via their indices
|
||||||
ReflectRef::TupleStruct(_) => {}
|
ReflectRef::TupleStruct(_) => {}
|
||||||
|
// `Tuple` is a special trait that can be manually implemented (instead of deriving Reflect). This exposes "tuple"
|
||||||
|
// operations on your type, allowing you to interact with fields via their indices. Tuple is automatically
|
||||||
|
// implemented for tuples of arity 12 or less.
|
||||||
|
ReflectRef::Tuple(_) => {}
|
||||||
// `List` is a special trait that can be manually implemented (instead of deriving Reflect). This exposes "list"
|
// `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
|
// operations on your type, such as indexing and insertion. List is automatically implemented for relevant core
|
||||||
// types like Vec<T>
|
// types like Vec<T>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user