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