Skip to content

Commit

Permalink
Fix Reflect serialization of tuple structs (#1366)
Browse files Browse the repository at this point in the history
* Fix  DynamicTupleStruct::type_name()

* Fix type_name() for DynamicList, DynamicMap  and DynamicTuple
  • Loading branch information
Davier authored Feb 2, 2021
1 parent 4796ea8 commit 5b11539
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 10 deletions.
1 change: 1 addition & 0 deletions crates/bevy_reflect/bevy_reflect_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_reflect/src/impls/std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
39 changes: 39 additions & 0 deletions crates/bevy_reflect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>()
);
}
}
15 changes: 13 additions & 2 deletions crates/bevy_reflect/src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,27 @@ 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(),
}
}
}

#[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));
}
Expand All @@ -49,6 +59,7 @@ impl List for DynamicList {

fn clone_dynamic(&self) -> DynamicList {
DynamicList {
name: self.name.clone(),
values: self
.values
.iter()
Expand All @@ -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]
Expand Down
16 changes: 13 additions & 3 deletions crates/bevy_reflect/src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down Expand Up @@ -65,6 +74,7 @@ impl Map for DynamicMap {

fn clone_dynamic(&self) -> DynamicMap {
DynamicMap {
name: self.name.clone(),
values: self
.values
.iter()
Expand All @@ -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 {
Expand Down
36 changes: 32 additions & 4 deletions crates/bevy_reflect/src/tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(')');
}
}

Expand Down Expand Up @@ -105,6 +129,7 @@ impl Tuple for DynamicTuple {
#[inline]
fn clone_dynamic(&self) -> DynamicTuple {
DynamicTuple {
name: self.name.clone(),
fields: self
.fields
.iter()
Expand All @@ -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]
Expand Down Expand Up @@ -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
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_reflect/src/tuple_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down

0 comments on commit 5b11539

Please sign in to comment.