This crate enables you to dynamically interact with Rust types:
```rust ignore // this will automatically implement the Reflect trait and the Struct trait (because the type is a struct)
struct Foo {
a: u32,
b: Bar,
c: Vec
// this will automatically implement the Reflect trait and the TupleStruct trait (because the type is a tuple struct)
struct Bar(String);
struct Baz { value: f32, }
// We will use this value to illustrate bevy_reflect
features
let mut foo = Foo {
a: 1,
b: Bar("hello".to_string()),
c: vec![1, 2],
d: vec![Baz { value: 3.14 }],
};
```
```rust ignore
asserteq!(*foo.getfield::
*foo.getfieldmut::
assert_eq!(foo.a, 2); ```
```rust ignore let mut dynamicstruct = DynamicStruct::default(); dynamicstruct.insert("a", 42u32); dynamic_struct.insert("c", vec![3, 4, 5]);
foo.apply(&dynamic_struct);
asserteq!(foo.a, 42); asserteq!(foo.c, vec![3, 4, 5]); ```
rust ignore
let value = *foo.get_path::<f32>("d[0].value").unwrap();
assert_eq!(value, 3.14);
rust ignore
for (i, value: &Reflect) in foo.iter_fields().enumerate() {
let field_name = foo.name_at(i).unwrap();
if let Some(value) = value.downcast_ref::<u32>() {
println!("{} is a u32 with the value: {}", field_name, *value);
}
}
```rust ignore
let mut registry = TypeRegistry::default();
registry.register::
let serializer = ReflectSerializer::new(&foo, ®istry); let serialized = ron::ser::tostringpretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
let mut deserializer = ron::de::Deserializer::fromstr(&serialized).unwrap();
let reflectdeserializer = ReflectDeserializer::new(®istry);
let value = reflectdeserializer.deserialize(&mut deserializer).unwrap();
let dynamicstruct = value.take::
assert!(foo.reflectpartialeq(&dynamic_struct).unwrap()); ```
Call a trait on a given &dyn Reflect
reference without knowing the underlying type!
```rust ignore
struct MyType { value: String, }
impl DoThing for MyType { fn do_thing(&self) -> String { format!("{} World!", self.value) } }
pub trait DoThing { fn do_thing(&self) -> String; }
// First, lets box our type as a Box
// This means we no longer have direct access to MyType or its methods. We can only call Reflect methods on reflectvalue.
// What if we want to call do_thing
on our type? We could downcast using reflectvalue.downcast_ref::
// Normally in rust we would be out of luck at this point. Lets use our new reflection powers to do something cool!
let mut typeregistry = TypeRegistry::default();
typeregistry.register::
// The #[reflect] attribute we put on our DoThing trait generated a new ReflectDoThing
struct, which implements TypeData.
// This was added to MyType's TypeRegistration.
let reflectdothing = typeregistry
.gettypedata::
// We can use this generated type to convert our &dyn Reflect
reference to a &dyn DoThing
reference
let mytrait: &dyn DoThing = reflectdothing.get(&*reflectvalue).unwrap();
// Which means we can now call dothing(). Magic! println!("{}", mytrait.do_thing());
// This works because the #[reflect(MyTrait)] we put on MyType informed the Reflect derive to insert a new instance // of ReflectDoThing into MyType's registration. The instance knows how to cast &dyn Reflect to &dyn DoThing, because it // knows that &dyn Reflect should first be downcasted to &MyType, which can then be safely casted to &dyn DoThing ```
The whole point of Rust is static safety! Why build something that makes it easy to throw it all away?