Bevy Reflect

This crate enables you to dynamically interact with Rust types:

Features

Derive the Reflect traits

```rust // this will automatically implement the Reflect trait and the Struct trait (because the type is a struct)

[derive(Reflect)]

struct Foo { a: u32, b: Bar, c: Vec, d: Vec, }

// this will automatically implement the Reflect trait and the TupleStruct trait (because the type is a tuple struct)

[derive(Reflect)]

struct Bar(String);

[derive(Reflect)]

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 }], }; ```

Interact with fields using their names

```rust asserteq!(*foo.getfield::("a").unwrap(), 1);

*foo.getfieldmut::("a").unwrap() = 2;

assert_eq!(foo.a, 2); ```

"Patch" your types with new values

```rust 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]); ```

Look up nested fields using "path strings"

rust let value = *foo.get_path::<f32>("d[0].value").unwrap(); assert_eq!(value, 3.14);

Iterate over struct fields

rust for (i, value: &Reflect) in foo.iter_fields().enumerate() { let field_name = foo.name_at(i).unwrap(); if let Ok(value) = value.downcast_ref::<u32>() { println!("{} is a u32 with the value: {}", field_name, *value); } }

Automatically serialize and deserialize via Serde (without explicit serde impls)

```rust let mut registry = TypeRegistry::default(); registry.register::(); registry.register::(); registry.register::(); registry.register::(); registry.register::(); registry.register::();

let serializer = ReflectSerializer::new(&foo, &registry); let serialized = ron::ser::tostringpretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();

let mut deserializer = ron::de::Deserializer::fromstr(&serialized).unwrap(); let reflectdeserializer = ReflectDeserializer::new(&registry); let value = reflectdeserializer.deserialize(&mut deserializer).unwrap(); let dynamicstruct = value.take::().unwrap();

assert!(foo.reflectpartialeq(&dynamic_struct).unwrap()); ```

Trait "reflection"

Call a trait on a given &dyn Reflect reference without knowing the underlying type!

```rust

[derive(Reflect)]

[reflect(DoThing)]

struct MyType { value: String, }

impl DoThing for MyType { fn do_thing(&self) -> String { format!("{} World!", self.value) } }

[reflect_trait]

pub trait DoThing { fn do_thing(&self) -> String; }

// First, lets box our type as a Box let reflectvalue: Box = Box::new(MyType { value: "Hello".tostring(), });

// 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::(), but what if we // don't know the type at compile time?

// 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::(reflectvalue.type_id()) .unwrap();

// 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 MyType, because it // knows that &dyn Reflect should first be downcasted to &MyType, which can then be safely casted to &dyn MyType ```

Why make this?

The whole point of Rust is static safety! Why build something that makes it easy to throw it all away?