Fix Reflect serialization of tuple structs (#1366)

* Fix  DynamicTupleStruct::type_name()

* Fix type_name() for DynamicList, DynamicMap  and DynamicTuple
This commit is contained in:
davier 2021-02-02 21:57:26 +00:00 committed by GitHub
parent 4796ea8d22
commit 5b115397ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 100 additions and 10 deletions

View File

@ -376,6 +376,7 @@ fn impl_tuple_struct(
fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicTupleStruct {
let mut dynamic = #bevy_reflect_path::DynamicTupleStruct::default();
dynamic.set_name(self.type_name().to_string());
#(dynamic.insert_boxed(self.#field_idents.clone_value());)*
dynamic
}

View File

@ -143,6 +143,7 @@ impl<K: Reflect + Clone + Eq + Hash, V: Reflect + Clone> Map for HashMap<K, V> {
fn clone_dynamic(&self) -> DynamicMap {
let mut dynamic_map = DynamicMap::default();
dynamic_map.set_name(self.type_name().to_string());
for (k, v) in HashMap::iter(self) {
dynamic_map.insert_boxed(k.clone_value(), v.clone_value());
}

View File

@ -334,4 +334,43 @@ mod tests {
let y = x.take::<Bar>().unwrap();
assert_eq!(y, Bar { x: 2 });
}
#[test]
fn dynamic_names() {
let list = Vec::<usize>::new();
let dyn_list = list.clone_dynamic();
assert_eq!(dyn_list.type_name(), std::any::type_name::<Vec<usize>>());
let map = HashMap::<usize, String>::default();
let dyn_map = map.clone_dynamic();
assert_eq!(
dyn_map.type_name(),
std::any::type_name::<HashMap<usize, String>>()
);
let tuple = (0usize, "1".to_string(), 2.0f32);
let mut dyn_tuple = tuple.clone_dynamic();
dyn_tuple.insert::<usize>(3);
assert_eq!(
dyn_tuple.type_name(),
std::any::type_name::<(usize, String, f32, usize)>()
);
#[derive(Reflect)]
struct TestStruct {
a: usize,
}
let struct_ = TestStruct { a: 0 };
let dyn_struct = struct_.clone_dynamic();
assert_eq!(dyn_struct.type_name(), std::any::type_name::<TestStruct>());
#[derive(Reflect)]
struct TestTupleStruct(usize);
let tuple_struct = TestTupleStruct(0);
let dyn_tuple_struct = tuple_struct.clone_dynamic();
assert_eq!(
dyn_tuple_struct.type_name(),
std::any::type_name::<TestTupleStruct>()
);
}
}

View File

@ -14,6 +14,7 @@ pub trait List: Reflect {
fn iter(&self) -> ListIter;
fn clone_dynamic(&self) -> DynamicList {
DynamicList {
name: self.type_name().to_string(),
values: self.iter().map(|value| value.clone_value()).collect(),
}
}
@ -21,10 +22,19 @@ pub trait List: Reflect {
#[derive(Default)]
pub struct DynamicList {
pub(crate) values: Vec<Box<dyn Reflect>>,
name: String,
values: Vec<Box<dyn Reflect>>,
}
impl DynamicList {
pub fn name(&self) -> &str {
&self.name
}
pub fn set_name(&mut self, name: String) {
self.name = name;
}
pub fn push<T: Reflect>(&mut self, value: T) {
self.values.push(Box::new(value));
}
@ -49,6 +59,7 @@ impl List for DynamicList {
fn clone_dynamic(&self) -> DynamicList {
DynamicList {
name: self.name.clone(),
values: self
.values
.iter()
@ -72,7 +83,7 @@ impl List for DynamicList {
impl Reflect for DynamicList {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
self.name.as_str()
}
#[inline]

View File

@ -23,11 +23,20 @@ const HASH_ERROR: &str = "the given key does not support hashing";
#[derive(Default)]
pub struct DynamicMap {
pub values: Vec<(Box<dyn Reflect>, Box<dyn Reflect>)>,
pub indices: HashMap<u64, usize>,
name: String,
values: Vec<(Box<dyn Reflect>, Box<dyn Reflect>)>,
indices: HashMap<u64, usize>,
}
impl DynamicMap {
pub fn name(&self) -> &str {
&self.name
}
pub fn set_name(&mut self, name: String) {
self.name = name;
}
pub fn insert<K: Reflect, V: Reflect>(&mut self, key: K, value: V) {
self.insert_boxed(Box::new(key), Box::new(value));
}
@ -65,6 +74,7 @@ impl Map for DynamicMap {
fn clone_dynamic(&self) -> DynamicMap {
DynamicMap {
name: self.name.clone(),
values: self
.values
.iter()
@ -90,7 +100,7 @@ impl Map for DynamicMap {
impl Reflect for DynamicMap {
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
&self.name
}
fn any(&self) -> &dyn Any {

View File

@ -65,16 +65,40 @@ impl GetTupleField for dyn Tuple {
#[derive(Default)]
pub struct DynamicTuple {
pub(crate) fields: Vec<Box<dyn Reflect>>,
name: String,
fields: Vec<Box<dyn Reflect>>,
}
impl DynamicTuple {
pub fn name(&self) -> &str {
&self.name
}
pub fn set_name(&mut self, name: String) {
self.name = name;
}
pub fn insert_boxed(&mut self, value: Box<dyn Reflect>) {
self.fields.push(value);
self.generate_name();
}
pub fn insert<T: Reflect>(&mut self, value: T) {
self.insert_boxed(Box::new(value));
self.generate_name();
}
fn generate_name(&mut self) {
let name = &mut self.name;
name.clear();
name.push('(');
for (i, field) in self.fields.iter().enumerate() {
if i > 0 {
name.push_str(", ");
}
name.push_str(field.type_name());
}
name.push(')');
}
}
@ -105,6 +129,7 @@ impl Tuple for DynamicTuple {
#[inline]
fn clone_dynamic(&self) -> DynamicTuple {
DynamicTuple {
name: self.name.clone(),
fields: self
.fields
.iter()
@ -117,7 +142,7 @@ impl Tuple for DynamicTuple {
impl Reflect for DynamicTuple {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
self.name()
}
#[inline]
@ -237,12 +262,15 @@ macro_rules! impl_reflect_tuple {
#[inline]
fn clone_dynamic(&self) -> DynamicTuple {
DynamicTuple {
let mut dyn_tuple = DynamicTuple {
name: String::default(),
fields: self
.iter_fields()
.map(|value| value.clone_value())
.collect(),
}
};
dyn_tuple.generate_name();
dyn_tuple
}
}

View File

@ -126,7 +126,7 @@ impl TupleStruct for DynamicTupleStruct {
impl Reflect for DynamicTupleStruct {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
self.name.as_str()
}
#[inline]