pub trait PartialReflect:
DynamicTypePath
+ Send
+ Sync
+ 'static {
Show 21 methods
// Required methods
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>;
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect>;
fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static);
fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static);
fn try_into_reflect(
self: Box<Self>,
) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>;
fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>;
fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>;
fn try_apply(
&mut self,
value: &(dyn PartialReflect + 'static),
) -> Result<(), ApplyError>;
fn reflect_ref(&self) -> ReflectRef<'_>;
fn reflect_mut(&mut self) -> ReflectMut<'_>;
fn reflect_owned(self: Box<Self>) -> ReflectOwned;
// Provided methods
fn apply(&mut self, value: &(dyn PartialReflect + 'static)) { ... }
fn reflect_kind(&self) -> ReflectKind { ... }
fn to_dynamic(&self) -> Box<dyn PartialReflect> { ... }
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> { ... }
fn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
where T: 'static,
Self: Sized + TypePath { ... }
fn reflect_hash(&self) -> Option<u64> { ... }
fn reflect_partial_eq(
&self,
_value: &(dyn PartialReflect + 'static),
) -> Option<bool> { ... }
fn reflect_partial_cmp(
&self,
_value: &(dyn PartialReflect + 'static),
) -> Option<Ordering> { ... }
fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error> { ... }
fn is_dynamic(&self) -> bool { ... }
}Expand description
The foundational trait of bevy_reflect, used for accessing and modifying data dynamically.
This is a supertrait of Reflect,
meaning any type which implements Reflect implements PartialReflect by definition.
It’s recommended to use the derive macro for Reflect rather than manually implementing this trait.
Doing so will automatically implement this trait as well as many other useful traits for reflection,
including one of the appropriate subtraits: Struct, TupleStruct or Enum.
See the crate-level documentation to see how this trait and its subtraits can be used.
Required Methods§
Sourcefn get_represented_type_info(&self) -> Option<&'static TypeInfo>
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
Returns the TypeInfo of the type represented by this value.
For most types, this will simply return their own TypeInfo.
However, for dynamic types, such as DynamicStruct or DynamicList,
this will return the type they represent
(or None if they don’t represent any particular type).
This method is great if you have an instance of a type or a dyn Reflect,
and want to access its TypeInfo. However, if this method is to be called
frequently, consider using TypeRegistry::get_type_info as it can be more
performant for such use cases.
Sourcefn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect>
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect>
Casts this type to a boxed, reflected value.
This is useful for coercing trait objects.
Sourcefn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)
fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)
Casts this type to a reflected value.
This is useful for coercing trait objects.
Sourcefn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)
fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)
Casts this type to a mutable, reflected value.
This is useful for coercing trait objects.
Sourcefn try_into_reflect(
self: Box<Self>,
) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>
fn try_into_reflect( self: Box<Self>, ) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>
Attempts to cast this type to a boxed, fully-reflected value.
Sourcefn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>
fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>
Attempts to cast this type to a fully-reflected value.
Sourcefn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>
fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>
Attempts to cast this type to a mutable, fully-reflected value.
Sourcefn try_apply(
&mut self,
value: &(dyn PartialReflect + 'static),
) -> Result<(), ApplyError>
fn try_apply( &mut self, value: &(dyn PartialReflect + 'static), ) -> Result<(), ApplyError>
Tries to apply a reflected value to this value.
Functions the same as the apply function but returns an error instead of
panicking.
§Handling Errors
This function may leave self in a partially mutated state if a error was encountered on the way.
consider maintaining a cloned instance of this data you can switch to if a error is encountered.
Sourcefn reflect_ref(&self) -> ReflectRef<'_>
fn reflect_ref(&self) -> ReflectRef<'_>
Returns an immutable enumeration of “kinds” of type.
See ReflectRef.
Sourcefn reflect_mut(&mut self) -> ReflectMut<'_>
fn reflect_mut(&mut self) -> ReflectMut<'_>
Returns a mutable enumeration of “kinds” of type.
See ReflectMut.
Sourcefn reflect_owned(self: Box<Self>) -> ReflectOwned
fn reflect_owned(self: Box<Self>) -> ReflectOwned
Returns an owned enumeration of “kinds” of type.
See ReflectOwned.
Provided Methods§
Sourcefn apply(&mut self, value: &(dyn PartialReflect + 'static))
fn apply(&mut self, value: &(dyn PartialReflect + 'static))
Applies a reflected value to this value.
If Self implements a reflection subtrait, then the semantics of this
method are as follows:
- If
Selfis aStruct, then the value of each named field ofvalueis applied to the corresponding named field ofself. Fields which are not present in both structs are ignored. - If
Selfis aTupleStructorTuple, then the value of each numbered field is applied to the corresponding numbered field ofself.Fields which are not present in both values are ignored. - If
Selfis anEnum, then the variant ofselfisupdatedto match the variant ofvalue. The corresponding fields of that variant are applied fromvalueontoself. Fields which are not present in both values are ignored. - If
Selfis aListorArray, then each element ofvalueis applied to the corresponding element ofself. Up toself.len()items are applied, and excess elements invalueare appended toself. - If
Selfis aMap, then for each key invalue, the associated value is applied to the value associated with the same key inself. Keys which are not present inselfare inserted, and keys fromselfwhich are not present invalueare removed. - If
Selfis aSet, then each element ofvalueis applied to the corresponding element ofSelf. If an element ofvaluedoes not exist inSelfthen it is cloned and inserted. If an element fromselfis not present invaluethen it is removed. - If
Selfis none of these, thenvalueis downcast toSelf, cloned, and assigned toself.
Note that Reflect must be implemented manually for Lists,
Maps, and Sets in order to achieve the correct semantics, as derived
implementations will have the semantics for Struct, TupleStruct, Enum
or none of the above depending on the kind of type. For lists, maps, and sets, use the
list_apply, map_apply, and set_apply helper functions when implementing this method.
§Panics
Derived implementations of this method will panic:
- If the type of
valueis not of the same kind asSelf(e.g. ifSelfis aList, whilevalueis aStruct). - If
Selfis any complex type and the corresponding fields or elements ofselfandvalueare not of the same type. - If
Selfis an opaque type andvaluecannot be downcast toSelf
Examples found in repository?
55fn setup(type_registry: Res<AppTypeRegistry>) {
56 let mut value = Foo {
57 a: 1,
58 _ignored: NonReflectedValue { _a: 10 },
59 nested: Bar { b: 8 },
60 };
61
62 // You can set field values like this. The type must match exactly or this will fail.
63 *value.get_field_mut("a").unwrap() = 2usize;
64 assert_eq!(value.a, 2);
65 assert_eq!(*value.get_field::<usize>("a").unwrap(), 2);
66
67 // You can also get the `&dyn PartialReflect` value of a field like this
68 let field = value.field("a").unwrap();
69
70 // But values introspected via `PartialReflect` will not return `dyn Reflect` trait objects
71 // (even if the containing type does implement `Reflect`), so we need to convert them:
72 let fully_reflected_field = field.try_as_reflect().unwrap();
73
74 // Now, you can downcast your `Reflect` value like this:
75 assert_eq!(*fully_reflected_field.downcast_ref::<usize>().unwrap(), 2);
76
77 // For this specific case, we also support the shortcut `try_downcast_ref`:
78 assert_eq!(*field.try_downcast_ref::<usize>().unwrap(), 2);
79
80 // `DynamicStruct` also implements the `Struct` and `Reflect` traits.
81 let mut patch = DynamicStruct::default();
82 patch.insert("a", 4usize);
83
84 // You can "apply" Reflect implementations on top of other Reflect implementations.
85 // This will only set fields with the same name, and it will fail if the types don't match.
86 // You can use this to "patch" your types with new values.
87 value.apply(&patch);
88 assert_eq!(value.a, 4);
89
90 let type_registry = type_registry.read();
91 // By default, all derived `Reflect` types can be Serialized using serde. No need to derive
92 // Serialize!
93 let serializer = ReflectSerializer::new(&value, &type_registry);
94 let ron_string =
95 ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
96 info!("{}\n", ron_string);
97
98 // Dynamic properties can be deserialized
99 let reflect_deserializer = ReflectDeserializer::new(&type_registry);
100 let mut deserializer = ron::de::Deserializer::from_str(&ron_string).unwrap();
101 let reflect_value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
102
103 // Deserializing returns a `Box<dyn PartialReflect>` value.
104 // Generally, deserializing a value will return the "dynamic" variant of a type.
105 // For example, deserializing a struct will return the DynamicStruct type.
106 // "Opaque types" will be deserialized as themselves.
107 assert_eq!(
108 reflect_value.reflect_type_path(),
109 DynamicStruct::type_path(),
110 );
111
112 // Reflect has its own `partial_eq` implementation, named `reflect_partial_eq`. This behaves
113 // like normal `partial_eq`, but it treats "dynamic" and "non-dynamic" types the same. The
114 // `Foo` struct and deserialized `DynamicStruct` are considered equal for this reason:
115 assert!(reflect_value.reflect_partial_eq(&value).unwrap());
116
117 // By "patching" `Foo` with the deserialized DynamicStruct, we can "Deserialize" Foo.
118 // This means we can serialize and deserialize with a single `Reflect` derive!
119 value.apply(&*reflect_value);
120}More examples
67fn setup() {
68 let mut z = <HashMap<_, _>>::default();
69 z.insert("Hello".to_string(), 1.0);
70 let value: Box<dyn Reflect> = Box::new(A {
71 x: 1,
72 y: vec![1, 2],
73 z,
74 });
75
76 // There are a number of different "reflect traits", which each expose different operations on
77 // the underlying type
78 match value.reflect_ref() {
79 // `Struct` is a trait automatically implemented for structs that derive Reflect. This trait
80 // allows you to interact with fields via their string names or indices
81 ReflectRef::Struct(value) => {
82 info!(
83 "This is a 'struct' type with an 'x' value of {}",
84 value.get_field::<usize>("x").unwrap()
85 );
86 }
87 // `TupleStruct` is a trait automatically implemented for tuple structs that derive Reflect.
88 // This trait allows you to interact with fields via their indices
89 ReflectRef::TupleStruct(_) => {}
90 // `Tuple` is a special trait that can be manually implemented (instead of deriving
91 // Reflect). This exposes "tuple" operations on your type, allowing you to interact
92 // with fields via their indices. Tuple is automatically implemented for tuples of
93 // arity 12 or less.
94 ReflectRef::Tuple(_) => {}
95 // `Enum` is a trait automatically implemented for enums that derive Reflect. This trait allows you
96 // to interact with the current variant and its fields (if it has any)
97 ReflectRef::Enum(_) => {}
98 // `List` is a special trait that can be manually implemented (instead of deriving Reflect).
99 // This exposes "list" operations on your type, such as insertion. `List` is automatically
100 // implemented for relevant core types like Vec<T>.
101 ReflectRef::List(_) => {}
102 // `Array` is a special trait that can be manually implemented (instead of deriving Reflect).
103 // This exposes "array" operations on your type, such as indexing. `Array`
104 // is automatically implemented for relevant core types like [T; N].
105 ReflectRef::Array(_) => {}
106 // `Map` is a special trait that can be manually implemented (instead of deriving Reflect).
107 // This exposes "map" operations on your type, such as getting / inserting by key.
108 // Map is automatically implemented for relevant core types like HashMap<K, V>
109 ReflectRef::Map(_) => {}
110 // `Set` is a special trait that can be manually implemented (instead of deriving Reflect).
111 // This exposes "set" operations on your type, such as getting / inserting by value.
112 // Set is automatically implemented for relevant core types like HashSet<T>
113 ReflectRef::Set(_) => {}
114 // `Function` is a special trait that can be manually implemented (instead of deriving Reflect).
115 // This exposes "function" operations on your type, such as calling it with arguments.
116 // This trait is automatically implemented for types like DynamicFunction.
117 // This variant only exists if the `reflect_functions` feature is enabled.
118 #[cfg(feature = "reflect_functions")]
119 ReflectRef::Function(_) => {}
120 // `Opaque` types do not implement any of the other traits above. They are simply a Reflect
121 // implementation. Opaque is implemented for opaque types like String and Instant,
122 // but also include primitive types like i32, usize, and f32 (despite not technically being opaque).
123 ReflectRef::Opaque(_) => {}
124 #[expect(
125 clippy::allow_attributes,
126 reason = "`unreachable_patterns` is not always linted"
127 )]
128 #[allow(
129 unreachable_patterns,
130 reason = "This example cannot always detect when `bevy_reflect/functions` is enabled."
131 )]
132 _ => {}
133 }
134
135 let mut dynamic_list = DynamicList::default();
136 dynamic_list.push(3u32);
137 dynamic_list.push(4u32);
138 dynamic_list.push(5u32);
139
140 let mut value: A = value.take::<A>().unwrap();
141 value.y.apply(&dynamic_list);
142 assert_eq!(value.y, vec![3u32, 4u32, 5u32]);
143
144 // reference types defined above that are only used to demonstrate reflect
145 // derive functionality:
146 _ = || -> (A, B, C, D, E, F) { unreachable!() };
147}20fn main() {
21 #[derive(Reflect, Default, PartialEq, Debug)]
22 #[reflect(Identifiable, Default)]
23 struct Player {
24 id: u32,
25 }
26
27 #[reflect_trait]
28 trait Identifiable {
29 fn id(&self) -> u32;
30 }
31
32 impl Identifiable for Player {
33 fn id(&self) -> u32 {
34 self.id
35 }
36 }
37
38 // Normally, when instantiating a type, you get back exactly that type.
39 // This is because the type is known at compile time.
40 // We call this the "concrete" or "canonical" type.
41 let player: Player = Player { id: 123 };
42
43 // When working with reflected types, however, we often "erase" this type information
44 // using the `Reflect` trait object.
45 // This trait object also gives us access to all the methods in the `PartialReflect` trait too.
46 // The underlying type is still the same (in this case, `Player`),
47 // but now we've hidden that information from the compiler.
48 let reflected: Box<dyn Reflect> = Box::new(player);
49
50 // Because it's the same type under the hood, we can still downcast it back to the original type.
51 assert!(reflected.downcast_ref::<Player>().is_some());
52
53 // We can attempt to clone our value using `PartialReflect::reflect_clone`.
54 // This will recursively call `PartialReflect::reflect_clone` on all fields of the type.
55 // Or, if we had registered `ReflectClone` using `#[reflect(Clone)]`, it would simply call `Clone::clone` directly.
56 let cloned: Box<dyn Reflect> = reflected.reflect_clone().unwrap();
57 assert_eq!(cloned.downcast_ref::<Player>(), Some(&Player { id: 123 }));
58
59 // Another way we can "clone" our data is by converting it to a dynamic type.
60 // Notice here we bind it as a `dyn PartialReflect` instead of `dyn Reflect`.
61 // This is because it returns a dynamic type that simply represents the original type.
62 // In this case, because `Player` is a struct, it will return a `DynamicStruct`.
63 let dynamic: Box<dyn PartialReflect> = reflected.to_dynamic();
64 assert!(dynamic.is_dynamic());
65
66 // And if we try to convert it back to a `dyn Reflect` trait object, we'll get `None`.
67 // Dynamic types cannot be directly cast to `dyn Reflect` trait objects.
68 assert!(dynamic.try_as_reflect().is_none());
69
70 // Generally dynamic types are used to represent (or "proxy") the original type,
71 // so that we can continue to access its fields and overall structure.
72 let dynamic_ref = dynamic.reflect_ref().as_struct().unwrap();
73 let id = dynamic_ref.field("id").unwrap().try_downcast_ref::<u32>();
74 assert_eq!(id, Some(&123));
75
76 // It also enables us to create a representation of a type without having compile-time
77 // access to the actual type. This is how the reflection deserializers work.
78 // They generally can't know how to construct a type ahead of time,
79 // so they instead build and return these dynamic representations.
80 let input = "(id: 123)";
81 let mut registry = TypeRegistry::default();
82 registry.register::<Player>();
83 let registration = registry.get(std::any::TypeId::of::<Player>()).unwrap();
84 let deserialized = TypedReflectDeserializer::new(registration, ®istry)
85 .deserialize(&mut ron::Deserializer::from_str(input).unwrap())
86 .unwrap();
87
88 // Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`.
89 assert!(deserialized.represents::<Player>());
90
91 // And while this does allow us to access the fields and structure of the type,
92 // there may be instances where we need the actual type.
93 // For example, if we want to convert our `dyn Reflect` into a `dyn Identifiable`,
94 // we can't use the `DynamicStruct` proxy.
95 let reflect_identifiable = registration
96 .data::<ReflectIdentifiable>()
97 .expect("`ReflectIdentifiable` should be registered");
98
99 // Trying to access the registry with our `deserialized` will give a compile error
100 // since it doesn't implement `Reflect`, only `PartialReflect`.
101 // Similarly, trying to force the operation will fail.
102 // This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`.
103 assert!(deserialized
104 .try_as_reflect()
105 .and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj))
106 .is_none());
107
108 // So how can we go from a dynamic type to a concrete type?
109 // There are two ways:
110
111 // 1. Using `PartialReflect::apply`.
112 {
113 // If you know the type at compile time, you can construct a new value and apply the dynamic
114 // value to it.
115 let mut value = Player::default();
116 value.apply(deserialized.as_ref());
117 assert_eq!(value.id, 123);
118
119 // If you don't know the type at compile time, you need a dynamic way of constructing
120 // an instance of the type. One such way is to use the `ReflectDefault` type data.
121 let reflect_default = registration
122 .data::<ReflectDefault>()
123 .expect("`ReflectDefault` should be registered");
124
125 let mut value: Box<dyn Reflect> = reflect_default.default();
126 value.apply(deserialized.as_ref());
127
128 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
129 assert_eq!(identifiable.id(), 123);
130 }
131
132 // 2. Using `FromReflect`
133 {
134 // If you know the type at compile time, you can use the `FromReflect` trait to convert the
135 // dynamic value into the concrete type directly.
136 let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap();
137 assert_eq!(value.id, 123);
138
139 // If you don't know the type at compile time, you can use the `ReflectFromReflect` type data
140 // to perform the conversion dynamically.
141 let reflect_from_reflect = registration
142 .data::<ReflectFromReflect>()
143 .expect("`ReflectFromReflect` should be registered");
144
145 let value: Box<dyn Reflect> = reflect_from_reflect
146 .from_reflect(deserialized.as_ref())
147 .unwrap();
148 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
149 assert_eq!(identifiable.id(), 123);
150 }
151
152 // Lastly, while dynamic types are commonly generated via reflection methods like
153 // `PartialReflect::to_dynamic` or via the reflection deserializers,
154 // you can also construct them manually.
155 let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
156
157 // This is useful when you just need to apply some subset of changes to a type.
158 let mut my_list: Vec<u32> = Vec::new();
159 my_list.apply(&my_dynamic_list);
160 assert_eq!(my_list, vec![1, 2, 3]);
161
162 // And if you want it to actually proxy a type, you can configure it to do that as well:
163 assert!(!my_dynamic_list
164 .as_partial_reflect()
165 .represents::<Vec<u32>>());
166 my_dynamic_list.set_represented_type(Some(<Vec<u32>>::type_info()));
167 assert!(my_dynamic_list
168 .as_partial_reflect()
169 .represents::<Vec<u32>>());
170
171 // ============================= REFERENCE ============================= //
172 // For reference, here are all the available dynamic types:
173
174 // 1. `DynamicTuple`
175 {
176 let mut dynamic_tuple = DynamicTuple::default();
177 dynamic_tuple.insert(1u32);
178 dynamic_tuple.insert(2u32);
179 dynamic_tuple.insert(3u32);
180
181 let mut my_tuple: (u32, u32, u32) = (0, 0, 0);
182 my_tuple.apply(&dynamic_tuple);
183 assert_eq!(my_tuple, (1, 2, 3));
184 }
185
186 // 2. `DynamicArray`
187 {
188 let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);
189
190 let mut my_array = [0u32; 3];
191 my_array.apply(&dynamic_array);
192 assert_eq!(my_array, [1, 2, 3]);
193 }
194
195 // 3. `DynamicList`
196 {
197 let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
198
199 let mut my_list: Vec<u32> = Vec::new();
200 my_list.apply(&dynamic_list);
201 assert_eq!(my_list, vec![1, 2, 3]);
202 }
203
204 // 4. `DynamicSet`
205 {
206 let mut dynamic_set = DynamicSet::from_iter(["x", "y", "z"]);
207 assert!(dynamic_set.contains(&"x"));
208
209 dynamic_set.remove(&"y");
210
211 let mut my_set: HashSet<&str> = HashSet::default();
212 my_set.apply(&dynamic_set);
213 assert_eq!(my_set, HashSet::from_iter(["x", "z"]));
214 }
215
216 // 5. `DynamicMap`
217 {
218 let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);
219
220 let mut my_map: HashMap<&str, u32> = HashMap::default();
221 my_map.apply(&dynamic_map);
222 assert_eq!(my_map.get("x"), Some(&1));
223 assert_eq!(my_map.get("y"), Some(&2));
224 assert_eq!(my_map.get("z"), Some(&3));
225 }
226
227 // 6. `DynamicStruct`
228 {
229 #[derive(Reflect, Default, Debug, PartialEq)]
230 struct MyStruct {
231 x: u32,
232 y: u32,
233 z: u32,
234 }
235
236 let mut dynamic_struct = DynamicStruct::default();
237 dynamic_struct.insert("x", 1u32);
238 dynamic_struct.insert("y", 2u32);
239 dynamic_struct.insert("z", 3u32);
240
241 let mut my_struct = MyStruct::default();
242 my_struct.apply(&dynamic_struct);
243 assert_eq!(my_struct, MyStruct { x: 1, y: 2, z: 3 });
244 }
245
246 // 7. `DynamicTupleStruct`
247 {
248 #[derive(Reflect, Default, Debug, PartialEq)]
249 struct MyTupleStruct(u32, u32, u32);
250
251 let mut dynamic_tuple_struct = DynamicTupleStruct::default();
252 dynamic_tuple_struct.insert(1u32);
253 dynamic_tuple_struct.insert(2u32);
254 dynamic_tuple_struct.insert(3u32);
255
256 let mut my_tuple_struct = MyTupleStruct::default();
257 my_tuple_struct.apply(&dynamic_tuple_struct);
258 assert_eq!(my_tuple_struct, MyTupleStruct(1, 2, 3));
259 }
260
261 // 8. `DynamicEnum`
262 {
263 #[derive(Reflect, Default, Debug, PartialEq)]
264 enum MyEnum {
265 #[default]
266 Empty,
267 Xyz(u32, u32, u32),
268 }
269
270 let mut values = DynamicTuple::default();
271 values.insert(1u32);
272 values.insert(2u32);
273 values.insert(3u32);
274
275 let dynamic_variant = DynamicVariant::Tuple(values);
276 let dynamic_enum = DynamicEnum::new("Xyz", dynamic_variant);
277
278 let mut my_enum = MyEnum::default();
279 my_enum.apply(&dynamic_enum);
280 assert_eq!(my_enum, MyEnum::Xyz(1, 2, 3));
281 }
282}Sourcefn reflect_kind(&self) -> ReflectKind
fn reflect_kind(&self) -> ReflectKind
Returns a zero-sized enumeration of “kinds” of type.
See ReflectKind.
Sourcefn to_dynamic(&self) -> Box<dyn PartialReflect>
fn to_dynamic(&self) -> Box<dyn PartialReflect>
Converts this reflected value into its dynamic representation based on its kind.
For example, a List type will internally invoke List::to_dynamic_list, returning DynamicList.
A Struct type will invoke Struct::to_dynamic_struct, returning DynamicStruct.
And so on.
If the kind is opaque, then the value will attempt to be cloned directly via reflect_clone,
since opaque types do not have any standard dynamic representation.
To attempt to clone the value directly such that it returns a concrete instance of this type,
use reflect_clone.
§Panics
This method will panic if the kind is opaque and the call to reflect_clone fails.
§Example
let value = (1, true, 3.14);
let dynamic_value = value.to_dynamic();
assert!(dynamic_value.is_dynamic())Examples found in repository?
20fn main() {
21 #[derive(Reflect, Default, PartialEq, Debug)]
22 #[reflect(Identifiable, Default)]
23 struct Player {
24 id: u32,
25 }
26
27 #[reflect_trait]
28 trait Identifiable {
29 fn id(&self) -> u32;
30 }
31
32 impl Identifiable for Player {
33 fn id(&self) -> u32 {
34 self.id
35 }
36 }
37
38 // Normally, when instantiating a type, you get back exactly that type.
39 // This is because the type is known at compile time.
40 // We call this the "concrete" or "canonical" type.
41 let player: Player = Player { id: 123 };
42
43 // When working with reflected types, however, we often "erase" this type information
44 // using the `Reflect` trait object.
45 // This trait object also gives us access to all the methods in the `PartialReflect` trait too.
46 // The underlying type is still the same (in this case, `Player`),
47 // but now we've hidden that information from the compiler.
48 let reflected: Box<dyn Reflect> = Box::new(player);
49
50 // Because it's the same type under the hood, we can still downcast it back to the original type.
51 assert!(reflected.downcast_ref::<Player>().is_some());
52
53 // We can attempt to clone our value using `PartialReflect::reflect_clone`.
54 // This will recursively call `PartialReflect::reflect_clone` on all fields of the type.
55 // Or, if we had registered `ReflectClone` using `#[reflect(Clone)]`, it would simply call `Clone::clone` directly.
56 let cloned: Box<dyn Reflect> = reflected.reflect_clone().unwrap();
57 assert_eq!(cloned.downcast_ref::<Player>(), Some(&Player { id: 123 }));
58
59 // Another way we can "clone" our data is by converting it to a dynamic type.
60 // Notice here we bind it as a `dyn PartialReflect` instead of `dyn Reflect`.
61 // This is because it returns a dynamic type that simply represents the original type.
62 // In this case, because `Player` is a struct, it will return a `DynamicStruct`.
63 let dynamic: Box<dyn PartialReflect> = reflected.to_dynamic();
64 assert!(dynamic.is_dynamic());
65
66 // And if we try to convert it back to a `dyn Reflect` trait object, we'll get `None`.
67 // Dynamic types cannot be directly cast to `dyn Reflect` trait objects.
68 assert!(dynamic.try_as_reflect().is_none());
69
70 // Generally dynamic types are used to represent (or "proxy") the original type,
71 // so that we can continue to access its fields and overall structure.
72 let dynamic_ref = dynamic.reflect_ref().as_struct().unwrap();
73 let id = dynamic_ref.field("id").unwrap().try_downcast_ref::<u32>();
74 assert_eq!(id, Some(&123));
75
76 // It also enables us to create a representation of a type without having compile-time
77 // access to the actual type. This is how the reflection deserializers work.
78 // They generally can't know how to construct a type ahead of time,
79 // so they instead build and return these dynamic representations.
80 let input = "(id: 123)";
81 let mut registry = TypeRegistry::default();
82 registry.register::<Player>();
83 let registration = registry.get(std::any::TypeId::of::<Player>()).unwrap();
84 let deserialized = TypedReflectDeserializer::new(registration, ®istry)
85 .deserialize(&mut ron::Deserializer::from_str(input).unwrap())
86 .unwrap();
87
88 // Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`.
89 assert!(deserialized.represents::<Player>());
90
91 // And while this does allow us to access the fields and structure of the type,
92 // there may be instances where we need the actual type.
93 // For example, if we want to convert our `dyn Reflect` into a `dyn Identifiable`,
94 // we can't use the `DynamicStruct` proxy.
95 let reflect_identifiable = registration
96 .data::<ReflectIdentifiable>()
97 .expect("`ReflectIdentifiable` should be registered");
98
99 // Trying to access the registry with our `deserialized` will give a compile error
100 // since it doesn't implement `Reflect`, only `PartialReflect`.
101 // Similarly, trying to force the operation will fail.
102 // This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`.
103 assert!(deserialized
104 .try_as_reflect()
105 .and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj))
106 .is_none());
107
108 // So how can we go from a dynamic type to a concrete type?
109 // There are two ways:
110
111 // 1. Using `PartialReflect::apply`.
112 {
113 // If you know the type at compile time, you can construct a new value and apply the dynamic
114 // value to it.
115 let mut value = Player::default();
116 value.apply(deserialized.as_ref());
117 assert_eq!(value.id, 123);
118
119 // If you don't know the type at compile time, you need a dynamic way of constructing
120 // an instance of the type. One such way is to use the `ReflectDefault` type data.
121 let reflect_default = registration
122 .data::<ReflectDefault>()
123 .expect("`ReflectDefault` should be registered");
124
125 let mut value: Box<dyn Reflect> = reflect_default.default();
126 value.apply(deserialized.as_ref());
127
128 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
129 assert_eq!(identifiable.id(), 123);
130 }
131
132 // 2. Using `FromReflect`
133 {
134 // If you know the type at compile time, you can use the `FromReflect` trait to convert the
135 // dynamic value into the concrete type directly.
136 let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap();
137 assert_eq!(value.id, 123);
138
139 // If you don't know the type at compile time, you can use the `ReflectFromReflect` type data
140 // to perform the conversion dynamically.
141 let reflect_from_reflect = registration
142 .data::<ReflectFromReflect>()
143 .expect("`ReflectFromReflect` should be registered");
144
145 let value: Box<dyn Reflect> = reflect_from_reflect
146 .from_reflect(deserialized.as_ref())
147 .unwrap();
148 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
149 assert_eq!(identifiable.id(), 123);
150 }
151
152 // Lastly, while dynamic types are commonly generated via reflection methods like
153 // `PartialReflect::to_dynamic` or via the reflection deserializers,
154 // you can also construct them manually.
155 let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
156
157 // This is useful when you just need to apply some subset of changes to a type.
158 let mut my_list: Vec<u32> = Vec::new();
159 my_list.apply(&my_dynamic_list);
160 assert_eq!(my_list, vec![1, 2, 3]);
161
162 // And if you want it to actually proxy a type, you can configure it to do that as well:
163 assert!(!my_dynamic_list
164 .as_partial_reflect()
165 .represents::<Vec<u32>>());
166 my_dynamic_list.set_represented_type(Some(<Vec<u32>>::type_info()));
167 assert!(my_dynamic_list
168 .as_partial_reflect()
169 .represents::<Vec<u32>>());
170
171 // ============================= REFERENCE ============================= //
172 // For reference, here are all the available dynamic types:
173
174 // 1. `DynamicTuple`
175 {
176 let mut dynamic_tuple = DynamicTuple::default();
177 dynamic_tuple.insert(1u32);
178 dynamic_tuple.insert(2u32);
179 dynamic_tuple.insert(3u32);
180
181 let mut my_tuple: (u32, u32, u32) = (0, 0, 0);
182 my_tuple.apply(&dynamic_tuple);
183 assert_eq!(my_tuple, (1, 2, 3));
184 }
185
186 // 2. `DynamicArray`
187 {
188 let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);
189
190 let mut my_array = [0u32; 3];
191 my_array.apply(&dynamic_array);
192 assert_eq!(my_array, [1, 2, 3]);
193 }
194
195 // 3. `DynamicList`
196 {
197 let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
198
199 let mut my_list: Vec<u32> = Vec::new();
200 my_list.apply(&dynamic_list);
201 assert_eq!(my_list, vec![1, 2, 3]);
202 }
203
204 // 4. `DynamicSet`
205 {
206 let mut dynamic_set = DynamicSet::from_iter(["x", "y", "z"]);
207 assert!(dynamic_set.contains(&"x"));
208
209 dynamic_set.remove(&"y");
210
211 let mut my_set: HashSet<&str> = HashSet::default();
212 my_set.apply(&dynamic_set);
213 assert_eq!(my_set, HashSet::from_iter(["x", "z"]));
214 }
215
216 // 5. `DynamicMap`
217 {
218 let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);
219
220 let mut my_map: HashMap<&str, u32> = HashMap::default();
221 my_map.apply(&dynamic_map);
222 assert_eq!(my_map.get("x"), Some(&1));
223 assert_eq!(my_map.get("y"), Some(&2));
224 assert_eq!(my_map.get("z"), Some(&3));
225 }
226
227 // 6. `DynamicStruct`
228 {
229 #[derive(Reflect, Default, Debug, PartialEq)]
230 struct MyStruct {
231 x: u32,
232 y: u32,
233 z: u32,
234 }
235
236 let mut dynamic_struct = DynamicStruct::default();
237 dynamic_struct.insert("x", 1u32);
238 dynamic_struct.insert("y", 2u32);
239 dynamic_struct.insert("z", 3u32);
240
241 let mut my_struct = MyStruct::default();
242 my_struct.apply(&dynamic_struct);
243 assert_eq!(my_struct, MyStruct { x: 1, y: 2, z: 3 });
244 }
245
246 // 7. `DynamicTupleStruct`
247 {
248 #[derive(Reflect, Default, Debug, PartialEq)]
249 struct MyTupleStruct(u32, u32, u32);
250
251 let mut dynamic_tuple_struct = DynamicTupleStruct::default();
252 dynamic_tuple_struct.insert(1u32);
253 dynamic_tuple_struct.insert(2u32);
254 dynamic_tuple_struct.insert(3u32);
255
256 let mut my_tuple_struct = MyTupleStruct::default();
257 my_tuple_struct.apply(&dynamic_tuple_struct);
258 assert_eq!(my_tuple_struct, MyTupleStruct(1, 2, 3));
259 }
260
261 // 8. `DynamicEnum`
262 {
263 #[derive(Reflect, Default, Debug, PartialEq)]
264 enum MyEnum {
265 #[default]
266 Empty,
267 Xyz(u32, u32, u32),
268 }
269
270 let mut values = DynamicTuple::default();
271 values.insert(1u32);
272 values.insert(2u32);
273 values.insert(3u32);
274
275 let dynamic_variant = DynamicVariant::Tuple(values);
276 let dynamic_enum = DynamicEnum::new("Xyz", dynamic_variant);
277
278 let mut my_enum = MyEnum::default();
279 my_enum.apply(&dynamic_enum);
280 assert_eq!(my_enum, MyEnum::Xyz(1, 2, 3));
281 }
282}Sourcefn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>
Attempts to clone Self using reflection.
Unlike to_dynamic, which generally returns a dynamic representation of Self,
this method attempts create a clone of Self directly, if possible.
If the clone cannot be performed, an appropriate ReflectCloneError is returned.
§Example
let value = (1, true, 3.14);
let cloned = value.reflect_clone().unwrap();
assert!(cloned.is::<(i32, bool, f64)>())Examples found in repository?
20fn main() {
21 #[derive(Reflect, Default, PartialEq, Debug)]
22 #[reflect(Identifiable, Default)]
23 struct Player {
24 id: u32,
25 }
26
27 #[reflect_trait]
28 trait Identifiable {
29 fn id(&self) -> u32;
30 }
31
32 impl Identifiable for Player {
33 fn id(&self) -> u32 {
34 self.id
35 }
36 }
37
38 // Normally, when instantiating a type, you get back exactly that type.
39 // This is because the type is known at compile time.
40 // We call this the "concrete" or "canonical" type.
41 let player: Player = Player { id: 123 };
42
43 // When working with reflected types, however, we often "erase" this type information
44 // using the `Reflect` trait object.
45 // This trait object also gives us access to all the methods in the `PartialReflect` trait too.
46 // The underlying type is still the same (in this case, `Player`),
47 // but now we've hidden that information from the compiler.
48 let reflected: Box<dyn Reflect> = Box::new(player);
49
50 // Because it's the same type under the hood, we can still downcast it back to the original type.
51 assert!(reflected.downcast_ref::<Player>().is_some());
52
53 // We can attempt to clone our value using `PartialReflect::reflect_clone`.
54 // This will recursively call `PartialReflect::reflect_clone` on all fields of the type.
55 // Or, if we had registered `ReflectClone` using `#[reflect(Clone)]`, it would simply call `Clone::clone` directly.
56 let cloned: Box<dyn Reflect> = reflected.reflect_clone().unwrap();
57 assert_eq!(cloned.downcast_ref::<Player>(), Some(&Player { id: 123 }));
58
59 // Another way we can "clone" our data is by converting it to a dynamic type.
60 // Notice here we bind it as a `dyn PartialReflect` instead of `dyn Reflect`.
61 // This is because it returns a dynamic type that simply represents the original type.
62 // In this case, because `Player` is a struct, it will return a `DynamicStruct`.
63 let dynamic: Box<dyn PartialReflect> = reflected.to_dynamic();
64 assert!(dynamic.is_dynamic());
65
66 // And if we try to convert it back to a `dyn Reflect` trait object, we'll get `None`.
67 // Dynamic types cannot be directly cast to `dyn Reflect` trait objects.
68 assert!(dynamic.try_as_reflect().is_none());
69
70 // Generally dynamic types are used to represent (or "proxy") the original type,
71 // so that we can continue to access its fields and overall structure.
72 let dynamic_ref = dynamic.reflect_ref().as_struct().unwrap();
73 let id = dynamic_ref.field("id").unwrap().try_downcast_ref::<u32>();
74 assert_eq!(id, Some(&123));
75
76 // It also enables us to create a representation of a type without having compile-time
77 // access to the actual type. This is how the reflection deserializers work.
78 // They generally can't know how to construct a type ahead of time,
79 // so they instead build and return these dynamic representations.
80 let input = "(id: 123)";
81 let mut registry = TypeRegistry::default();
82 registry.register::<Player>();
83 let registration = registry.get(std::any::TypeId::of::<Player>()).unwrap();
84 let deserialized = TypedReflectDeserializer::new(registration, ®istry)
85 .deserialize(&mut ron::Deserializer::from_str(input).unwrap())
86 .unwrap();
87
88 // Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`.
89 assert!(deserialized.represents::<Player>());
90
91 // And while this does allow us to access the fields and structure of the type,
92 // there may be instances where we need the actual type.
93 // For example, if we want to convert our `dyn Reflect` into a `dyn Identifiable`,
94 // we can't use the `DynamicStruct` proxy.
95 let reflect_identifiable = registration
96 .data::<ReflectIdentifiable>()
97 .expect("`ReflectIdentifiable` should be registered");
98
99 // Trying to access the registry with our `deserialized` will give a compile error
100 // since it doesn't implement `Reflect`, only `PartialReflect`.
101 // Similarly, trying to force the operation will fail.
102 // This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`.
103 assert!(deserialized
104 .try_as_reflect()
105 .and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj))
106 .is_none());
107
108 // So how can we go from a dynamic type to a concrete type?
109 // There are two ways:
110
111 // 1. Using `PartialReflect::apply`.
112 {
113 // If you know the type at compile time, you can construct a new value and apply the dynamic
114 // value to it.
115 let mut value = Player::default();
116 value.apply(deserialized.as_ref());
117 assert_eq!(value.id, 123);
118
119 // If you don't know the type at compile time, you need a dynamic way of constructing
120 // an instance of the type. One such way is to use the `ReflectDefault` type data.
121 let reflect_default = registration
122 .data::<ReflectDefault>()
123 .expect("`ReflectDefault` should be registered");
124
125 let mut value: Box<dyn Reflect> = reflect_default.default();
126 value.apply(deserialized.as_ref());
127
128 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
129 assert_eq!(identifiable.id(), 123);
130 }
131
132 // 2. Using `FromReflect`
133 {
134 // If you know the type at compile time, you can use the `FromReflect` trait to convert the
135 // dynamic value into the concrete type directly.
136 let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap();
137 assert_eq!(value.id, 123);
138
139 // If you don't know the type at compile time, you can use the `ReflectFromReflect` type data
140 // to perform the conversion dynamically.
141 let reflect_from_reflect = registration
142 .data::<ReflectFromReflect>()
143 .expect("`ReflectFromReflect` should be registered");
144
145 let value: Box<dyn Reflect> = reflect_from_reflect
146 .from_reflect(deserialized.as_ref())
147 .unwrap();
148 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
149 assert_eq!(identifiable.id(), 123);
150 }
151
152 // Lastly, while dynamic types are commonly generated via reflection methods like
153 // `PartialReflect::to_dynamic` or via the reflection deserializers,
154 // you can also construct them manually.
155 let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
156
157 // This is useful when you just need to apply some subset of changes to a type.
158 let mut my_list: Vec<u32> = Vec::new();
159 my_list.apply(&my_dynamic_list);
160 assert_eq!(my_list, vec![1, 2, 3]);
161
162 // And if you want it to actually proxy a type, you can configure it to do that as well:
163 assert!(!my_dynamic_list
164 .as_partial_reflect()
165 .represents::<Vec<u32>>());
166 my_dynamic_list.set_represented_type(Some(<Vec<u32>>::type_info()));
167 assert!(my_dynamic_list
168 .as_partial_reflect()
169 .represents::<Vec<u32>>());
170
171 // ============================= REFERENCE ============================= //
172 // For reference, here are all the available dynamic types:
173
174 // 1. `DynamicTuple`
175 {
176 let mut dynamic_tuple = DynamicTuple::default();
177 dynamic_tuple.insert(1u32);
178 dynamic_tuple.insert(2u32);
179 dynamic_tuple.insert(3u32);
180
181 let mut my_tuple: (u32, u32, u32) = (0, 0, 0);
182 my_tuple.apply(&dynamic_tuple);
183 assert_eq!(my_tuple, (1, 2, 3));
184 }
185
186 // 2. `DynamicArray`
187 {
188 let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);
189
190 let mut my_array = [0u32; 3];
191 my_array.apply(&dynamic_array);
192 assert_eq!(my_array, [1, 2, 3]);
193 }
194
195 // 3. `DynamicList`
196 {
197 let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
198
199 let mut my_list: Vec<u32> = Vec::new();
200 my_list.apply(&dynamic_list);
201 assert_eq!(my_list, vec![1, 2, 3]);
202 }
203
204 // 4. `DynamicSet`
205 {
206 let mut dynamic_set = DynamicSet::from_iter(["x", "y", "z"]);
207 assert!(dynamic_set.contains(&"x"));
208
209 dynamic_set.remove(&"y");
210
211 let mut my_set: HashSet<&str> = HashSet::default();
212 my_set.apply(&dynamic_set);
213 assert_eq!(my_set, HashSet::from_iter(["x", "z"]));
214 }
215
216 // 5. `DynamicMap`
217 {
218 let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);
219
220 let mut my_map: HashMap<&str, u32> = HashMap::default();
221 my_map.apply(&dynamic_map);
222 assert_eq!(my_map.get("x"), Some(&1));
223 assert_eq!(my_map.get("y"), Some(&2));
224 assert_eq!(my_map.get("z"), Some(&3));
225 }
226
227 // 6. `DynamicStruct`
228 {
229 #[derive(Reflect, Default, Debug, PartialEq)]
230 struct MyStruct {
231 x: u32,
232 y: u32,
233 z: u32,
234 }
235
236 let mut dynamic_struct = DynamicStruct::default();
237 dynamic_struct.insert("x", 1u32);
238 dynamic_struct.insert("y", 2u32);
239 dynamic_struct.insert("z", 3u32);
240
241 let mut my_struct = MyStruct::default();
242 my_struct.apply(&dynamic_struct);
243 assert_eq!(my_struct, MyStruct { x: 1, y: 2, z: 3 });
244 }
245
246 // 7. `DynamicTupleStruct`
247 {
248 #[derive(Reflect, Default, Debug, PartialEq)]
249 struct MyTupleStruct(u32, u32, u32);
250
251 let mut dynamic_tuple_struct = DynamicTupleStruct::default();
252 dynamic_tuple_struct.insert(1u32);
253 dynamic_tuple_struct.insert(2u32);
254 dynamic_tuple_struct.insert(3u32);
255
256 let mut my_tuple_struct = MyTupleStruct::default();
257 my_tuple_struct.apply(&dynamic_tuple_struct);
258 assert_eq!(my_tuple_struct, MyTupleStruct(1, 2, 3));
259 }
260
261 // 8. `DynamicEnum`
262 {
263 #[derive(Reflect, Default, Debug, PartialEq)]
264 enum MyEnum {
265 #[default]
266 Empty,
267 Xyz(u32, u32, u32),
268 }
269
270 let mut values = DynamicTuple::default();
271 values.insert(1u32);
272 values.insert(2u32);
273 values.insert(3u32);
274
275 let dynamic_variant = DynamicVariant::Tuple(values);
276 let dynamic_enum = DynamicEnum::new("Xyz", dynamic_variant);
277
278 let mut my_enum = MyEnum::default();
279 my_enum.apply(&dynamic_enum);
280 assert_eq!(my_enum, MyEnum::Xyz(1, 2, 3));
281 }
282}Sourcefn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
fn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
For a type implementing PartialReflect, combines reflect_clone and
take in a useful fashion, automatically constructing an appropriate
ReflectCloneError if the downcast fails.
Sourcefn reflect_hash(&self) -> Option<u64>
fn reflect_hash(&self) -> Option<u64>
Returns a hash of the value (which includes the type).
If the underlying type does not support hashing, returns None.
Sourcefn reflect_partial_eq(
&self,
_value: &(dyn PartialReflect + 'static),
) -> Option<bool>
fn reflect_partial_eq( &self, _value: &(dyn PartialReflect + 'static), ) -> Option<bool>
Returns a “partial equality” comparison result.
If the underlying type does not support equality testing, returns None.
Examples found in repository?
55fn setup(type_registry: Res<AppTypeRegistry>) {
56 let mut value = Foo {
57 a: 1,
58 _ignored: NonReflectedValue { _a: 10 },
59 nested: Bar { b: 8 },
60 };
61
62 // You can set field values like this. The type must match exactly or this will fail.
63 *value.get_field_mut("a").unwrap() = 2usize;
64 assert_eq!(value.a, 2);
65 assert_eq!(*value.get_field::<usize>("a").unwrap(), 2);
66
67 // You can also get the `&dyn PartialReflect` value of a field like this
68 let field = value.field("a").unwrap();
69
70 // But values introspected via `PartialReflect` will not return `dyn Reflect` trait objects
71 // (even if the containing type does implement `Reflect`), so we need to convert them:
72 let fully_reflected_field = field.try_as_reflect().unwrap();
73
74 // Now, you can downcast your `Reflect` value like this:
75 assert_eq!(*fully_reflected_field.downcast_ref::<usize>().unwrap(), 2);
76
77 // For this specific case, we also support the shortcut `try_downcast_ref`:
78 assert_eq!(*field.try_downcast_ref::<usize>().unwrap(), 2);
79
80 // `DynamicStruct` also implements the `Struct` and `Reflect` traits.
81 let mut patch = DynamicStruct::default();
82 patch.insert("a", 4usize);
83
84 // You can "apply" Reflect implementations on top of other Reflect implementations.
85 // This will only set fields with the same name, and it will fail if the types don't match.
86 // You can use this to "patch" your types with new values.
87 value.apply(&patch);
88 assert_eq!(value.a, 4);
89
90 let type_registry = type_registry.read();
91 // By default, all derived `Reflect` types can be Serialized using serde. No need to derive
92 // Serialize!
93 let serializer = ReflectSerializer::new(&value, &type_registry);
94 let ron_string =
95 ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
96 info!("{}\n", ron_string);
97
98 // Dynamic properties can be deserialized
99 let reflect_deserializer = ReflectDeserializer::new(&type_registry);
100 let mut deserializer = ron::de::Deserializer::from_str(&ron_string).unwrap();
101 let reflect_value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
102
103 // Deserializing returns a `Box<dyn PartialReflect>` value.
104 // Generally, deserializing a value will return the "dynamic" variant of a type.
105 // For example, deserializing a struct will return the DynamicStruct type.
106 // "Opaque types" will be deserialized as themselves.
107 assert_eq!(
108 reflect_value.reflect_type_path(),
109 DynamicStruct::type_path(),
110 );
111
112 // Reflect has its own `partial_eq` implementation, named `reflect_partial_eq`. This behaves
113 // like normal `partial_eq`, but it treats "dynamic" and "non-dynamic" types the same. The
114 // `Foo` struct and deserialized `DynamicStruct` are considered equal for this reason:
115 assert!(reflect_value.reflect_partial_eq(&value).unwrap());
116
117 // By "patching" `Foo` with the deserialized DynamicStruct, we can "Deserialize" Foo.
118 // This means we can serialize and deserialize with a single `Reflect` derive!
119 value.apply(&*reflect_value);
120}Sourcefn reflect_partial_cmp(
&self,
_value: &(dyn PartialReflect + 'static),
) -> Option<Ordering>
fn reflect_partial_cmp( &self, _value: &(dyn PartialReflect + 'static), ) -> Option<Ordering>
Returns a “partial comparison” result.
If the underlying type does not support it, returns None.
Sourcefn is_dynamic(&self) -> bool
fn is_dynamic(&self) -> bool
Indicates whether or not this type is a dynamic type.
Dynamic types include the ones built-in to this crate,
such as DynamicStruct, DynamicList, and DynamicTuple.
However, they may be custom types used as proxies for other types
or to facilitate scripting capabilities.
By default, this method will return false.
Examples found in repository?
20fn main() {
21 #[derive(Reflect, Default, PartialEq, Debug)]
22 #[reflect(Identifiable, Default)]
23 struct Player {
24 id: u32,
25 }
26
27 #[reflect_trait]
28 trait Identifiable {
29 fn id(&self) -> u32;
30 }
31
32 impl Identifiable for Player {
33 fn id(&self) -> u32 {
34 self.id
35 }
36 }
37
38 // Normally, when instantiating a type, you get back exactly that type.
39 // This is because the type is known at compile time.
40 // We call this the "concrete" or "canonical" type.
41 let player: Player = Player { id: 123 };
42
43 // When working with reflected types, however, we often "erase" this type information
44 // using the `Reflect` trait object.
45 // This trait object also gives us access to all the methods in the `PartialReflect` trait too.
46 // The underlying type is still the same (in this case, `Player`),
47 // but now we've hidden that information from the compiler.
48 let reflected: Box<dyn Reflect> = Box::new(player);
49
50 // Because it's the same type under the hood, we can still downcast it back to the original type.
51 assert!(reflected.downcast_ref::<Player>().is_some());
52
53 // We can attempt to clone our value using `PartialReflect::reflect_clone`.
54 // This will recursively call `PartialReflect::reflect_clone` on all fields of the type.
55 // Or, if we had registered `ReflectClone` using `#[reflect(Clone)]`, it would simply call `Clone::clone` directly.
56 let cloned: Box<dyn Reflect> = reflected.reflect_clone().unwrap();
57 assert_eq!(cloned.downcast_ref::<Player>(), Some(&Player { id: 123 }));
58
59 // Another way we can "clone" our data is by converting it to a dynamic type.
60 // Notice here we bind it as a `dyn PartialReflect` instead of `dyn Reflect`.
61 // This is because it returns a dynamic type that simply represents the original type.
62 // In this case, because `Player` is a struct, it will return a `DynamicStruct`.
63 let dynamic: Box<dyn PartialReflect> = reflected.to_dynamic();
64 assert!(dynamic.is_dynamic());
65
66 // And if we try to convert it back to a `dyn Reflect` trait object, we'll get `None`.
67 // Dynamic types cannot be directly cast to `dyn Reflect` trait objects.
68 assert!(dynamic.try_as_reflect().is_none());
69
70 // Generally dynamic types are used to represent (or "proxy") the original type,
71 // so that we can continue to access its fields and overall structure.
72 let dynamic_ref = dynamic.reflect_ref().as_struct().unwrap();
73 let id = dynamic_ref.field("id").unwrap().try_downcast_ref::<u32>();
74 assert_eq!(id, Some(&123));
75
76 // It also enables us to create a representation of a type without having compile-time
77 // access to the actual type. This is how the reflection deserializers work.
78 // They generally can't know how to construct a type ahead of time,
79 // so they instead build and return these dynamic representations.
80 let input = "(id: 123)";
81 let mut registry = TypeRegistry::default();
82 registry.register::<Player>();
83 let registration = registry.get(std::any::TypeId::of::<Player>()).unwrap();
84 let deserialized = TypedReflectDeserializer::new(registration, ®istry)
85 .deserialize(&mut ron::Deserializer::from_str(input).unwrap())
86 .unwrap();
87
88 // Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`.
89 assert!(deserialized.represents::<Player>());
90
91 // And while this does allow us to access the fields and structure of the type,
92 // there may be instances where we need the actual type.
93 // For example, if we want to convert our `dyn Reflect` into a `dyn Identifiable`,
94 // we can't use the `DynamicStruct` proxy.
95 let reflect_identifiable = registration
96 .data::<ReflectIdentifiable>()
97 .expect("`ReflectIdentifiable` should be registered");
98
99 // Trying to access the registry with our `deserialized` will give a compile error
100 // since it doesn't implement `Reflect`, only `PartialReflect`.
101 // Similarly, trying to force the operation will fail.
102 // This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`.
103 assert!(deserialized
104 .try_as_reflect()
105 .and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj))
106 .is_none());
107
108 // So how can we go from a dynamic type to a concrete type?
109 // There are two ways:
110
111 // 1. Using `PartialReflect::apply`.
112 {
113 // If you know the type at compile time, you can construct a new value and apply the dynamic
114 // value to it.
115 let mut value = Player::default();
116 value.apply(deserialized.as_ref());
117 assert_eq!(value.id, 123);
118
119 // If you don't know the type at compile time, you need a dynamic way of constructing
120 // an instance of the type. One such way is to use the `ReflectDefault` type data.
121 let reflect_default = registration
122 .data::<ReflectDefault>()
123 .expect("`ReflectDefault` should be registered");
124
125 let mut value: Box<dyn Reflect> = reflect_default.default();
126 value.apply(deserialized.as_ref());
127
128 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
129 assert_eq!(identifiable.id(), 123);
130 }
131
132 // 2. Using `FromReflect`
133 {
134 // If you know the type at compile time, you can use the `FromReflect` trait to convert the
135 // dynamic value into the concrete type directly.
136 let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap();
137 assert_eq!(value.id, 123);
138
139 // If you don't know the type at compile time, you can use the `ReflectFromReflect` type data
140 // to perform the conversion dynamically.
141 let reflect_from_reflect = registration
142 .data::<ReflectFromReflect>()
143 .expect("`ReflectFromReflect` should be registered");
144
145 let value: Box<dyn Reflect> = reflect_from_reflect
146 .from_reflect(deserialized.as_ref())
147 .unwrap();
148 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
149 assert_eq!(identifiable.id(), 123);
150 }
151
152 // Lastly, while dynamic types are commonly generated via reflection methods like
153 // `PartialReflect::to_dynamic` or via the reflection deserializers,
154 // you can also construct them manually.
155 let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
156
157 // This is useful when you just need to apply some subset of changes to a type.
158 let mut my_list: Vec<u32> = Vec::new();
159 my_list.apply(&my_dynamic_list);
160 assert_eq!(my_list, vec![1, 2, 3]);
161
162 // And if you want it to actually proxy a type, you can configure it to do that as well:
163 assert!(!my_dynamic_list
164 .as_partial_reflect()
165 .represents::<Vec<u32>>());
166 my_dynamic_list.set_represented_type(Some(<Vec<u32>>::type_info()));
167 assert!(my_dynamic_list
168 .as_partial_reflect()
169 .represents::<Vec<u32>>());
170
171 // ============================= REFERENCE ============================= //
172 // For reference, here are all the available dynamic types:
173
174 // 1. `DynamicTuple`
175 {
176 let mut dynamic_tuple = DynamicTuple::default();
177 dynamic_tuple.insert(1u32);
178 dynamic_tuple.insert(2u32);
179 dynamic_tuple.insert(3u32);
180
181 let mut my_tuple: (u32, u32, u32) = (0, 0, 0);
182 my_tuple.apply(&dynamic_tuple);
183 assert_eq!(my_tuple, (1, 2, 3));
184 }
185
186 // 2. `DynamicArray`
187 {
188 let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);
189
190 let mut my_array = [0u32; 3];
191 my_array.apply(&dynamic_array);
192 assert_eq!(my_array, [1, 2, 3]);
193 }
194
195 // 3. `DynamicList`
196 {
197 let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
198
199 let mut my_list: Vec<u32> = Vec::new();
200 my_list.apply(&dynamic_list);
201 assert_eq!(my_list, vec![1, 2, 3]);
202 }
203
204 // 4. `DynamicSet`
205 {
206 let mut dynamic_set = DynamicSet::from_iter(["x", "y", "z"]);
207 assert!(dynamic_set.contains(&"x"));
208
209 dynamic_set.remove(&"y");
210
211 let mut my_set: HashSet<&str> = HashSet::default();
212 my_set.apply(&dynamic_set);
213 assert_eq!(my_set, HashSet::from_iter(["x", "z"]));
214 }
215
216 // 5. `DynamicMap`
217 {
218 let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);
219
220 let mut my_map: HashMap<&str, u32> = HashMap::default();
221 my_map.apply(&dynamic_map);
222 assert_eq!(my_map.get("x"), Some(&1));
223 assert_eq!(my_map.get("y"), Some(&2));
224 assert_eq!(my_map.get("z"), Some(&3));
225 }
226
227 // 6. `DynamicStruct`
228 {
229 #[derive(Reflect, Default, Debug, PartialEq)]
230 struct MyStruct {
231 x: u32,
232 y: u32,
233 z: u32,
234 }
235
236 let mut dynamic_struct = DynamicStruct::default();
237 dynamic_struct.insert("x", 1u32);
238 dynamic_struct.insert("y", 2u32);
239 dynamic_struct.insert("z", 3u32);
240
241 let mut my_struct = MyStruct::default();
242 my_struct.apply(&dynamic_struct);
243 assert_eq!(my_struct, MyStruct { x: 1, y: 2, z: 3 });
244 }
245
246 // 7. `DynamicTupleStruct`
247 {
248 #[derive(Reflect, Default, Debug, PartialEq)]
249 struct MyTupleStruct(u32, u32, u32);
250
251 let mut dynamic_tuple_struct = DynamicTupleStruct::default();
252 dynamic_tuple_struct.insert(1u32);
253 dynamic_tuple_struct.insert(2u32);
254 dynamic_tuple_struct.insert(3u32);
255
256 let mut my_tuple_struct = MyTupleStruct::default();
257 my_tuple_struct.apply(&dynamic_tuple_struct);
258 assert_eq!(my_tuple_struct, MyTupleStruct(1, 2, 3));
259 }
260
261 // 8. `DynamicEnum`
262 {
263 #[derive(Reflect, Default, Debug, PartialEq)]
264 enum MyEnum {
265 #[default]
266 Empty,
267 Xyz(u32, u32, u32),
268 }
269
270 let mut values = DynamicTuple::default();
271 values.insert(1u32);
272 values.insert(2u32);
273 values.insert(3u32);
274
275 let dynamic_variant = DynamicVariant::Tuple(values);
276 let dynamic_enum = DynamicEnum::new("Xyz", dynamic_variant);
277
278 let mut my_enum = MyEnum::default();
279 my_enum.apply(&dynamic_enum);
280 assert_eq!(my_enum, MyEnum::Xyz(1, 2, 3));
281 }
282}Implementations§
Source§impl dyn PartialReflect
impl dyn PartialReflect
Sourcepub fn represents<T>(&self) -> bool
pub fn represents<T>(&self) -> bool
Returns true if the underlying value represents a value of type T, or false
otherwise.
Read is for more information on underlying values and represented types.
Examples found in repository?
20fn main() {
21 #[derive(Reflect, Default, PartialEq, Debug)]
22 #[reflect(Identifiable, Default)]
23 struct Player {
24 id: u32,
25 }
26
27 #[reflect_trait]
28 trait Identifiable {
29 fn id(&self) -> u32;
30 }
31
32 impl Identifiable for Player {
33 fn id(&self) -> u32 {
34 self.id
35 }
36 }
37
38 // Normally, when instantiating a type, you get back exactly that type.
39 // This is because the type is known at compile time.
40 // We call this the "concrete" or "canonical" type.
41 let player: Player = Player { id: 123 };
42
43 // When working with reflected types, however, we often "erase" this type information
44 // using the `Reflect` trait object.
45 // This trait object also gives us access to all the methods in the `PartialReflect` trait too.
46 // The underlying type is still the same (in this case, `Player`),
47 // but now we've hidden that information from the compiler.
48 let reflected: Box<dyn Reflect> = Box::new(player);
49
50 // Because it's the same type under the hood, we can still downcast it back to the original type.
51 assert!(reflected.downcast_ref::<Player>().is_some());
52
53 // We can attempt to clone our value using `PartialReflect::reflect_clone`.
54 // This will recursively call `PartialReflect::reflect_clone` on all fields of the type.
55 // Or, if we had registered `ReflectClone` using `#[reflect(Clone)]`, it would simply call `Clone::clone` directly.
56 let cloned: Box<dyn Reflect> = reflected.reflect_clone().unwrap();
57 assert_eq!(cloned.downcast_ref::<Player>(), Some(&Player { id: 123 }));
58
59 // Another way we can "clone" our data is by converting it to a dynamic type.
60 // Notice here we bind it as a `dyn PartialReflect` instead of `dyn Reflect`.
61 // This is because it returns a dynamic type that simply represents the original type.
62 // In this case, because `Player` is a struct, it will return a `DynamicStruct`.
63 let dynamic: Box<dyn PartialReflect> = reflected.to_dynamic();
64 assert!(dynamic.is_dynamic());
65
66 // And if we try to convert it back to a `dyn Reflect` trait object, we'll get `None`.
67 // Dynamic types cannot be directly cast to `dyn Reflect` trait objects.
68 assert!(dynamic.try_as_reflect().is_none());
69
70 // Generally dynamic types are used to represent (or "proxy") the original type,
71 // so that we can continue to access its fields and overall structure.
72 let dynamic_ref = dynamic.reflect_ref().as_struct().unwrap();
73 let id = dynamic_ref.field("id").unwrap().try_downcast_ref::<u32>();
74 assert_eq!(id, Some(&123));
75
76 // It also enables us to create a representation of a type without having compile-time
77 // access to the actual type. This is how the reflection deserializers work.
78 // They generally can't know how to construct a type ahead of time,
79 // so they instead build and return these dynamic representations.
80 let input = "(id: 123)";
81 let mut registry = TypeRegistry::default();
82 registry.register::<Player>();
83 let registration = registry.get(std::any::TypeId::of::<Player>()).unwrap();
84 let deserialized = TypedReflectDeserializer::new(registration, ®istry)
85 .deserialize(&mut ron::Deserializer::from_str(input).unwrap())
86 .unwrap();
87
88 // Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`.
89 assert!(deserialized.represents::<Player>());
90
91 // And while this does allow us to access the fields and structure of the type,
92 // there may be instances where we need the actual type.
93 // For example, if we want to convert our `dyn Reflect` into a `dyn Identifiable`,
94 // we can't use the `DynamicStruct` proxy.
95 let reflect_identifiable = registration
96 .data::<ReflectIdentifiable>()
97 .expect("`ReflectIdentifiable` should be registered");
98
99 // Trying to access the registry with our `deserialized` will give a compile error
100 // since it doesn't implement `Reflect`, only `PartialReflect`.
101 // Similarly, trying to force the operation will fail.
102 // This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`.
103 assert!(deserialized
104 .try_as_reflect()
105 .and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj))
106 .is_none());
107
108 // So how can we go from a dynamic type to a concrete type?
109 // There are two ways:
110
111 // 1. Using `PartialReflect::apply`.
112 {
113 // If you know the type at compile time, you can construct a new value and apply the dynamic
114 // value to it.
115 let mut value = Player::default();
116 value.apply(deserialized.as_ref());
117 assert_eq!(value.id, 123);
118
119 // If you don't know the type at compile time, you need a dynamic way of constructing
120 // an instance of the type. One such way is to use the `ReflectDefault` type data.
121 let reflect_default = registration
122 .data::<ReflectDefault>()
123 .expect("`ReflectDefault` should be registered");
124
125 let mut value: Box<dyn Reflect> = reflect_default.default();
126 value.apply(deserialized.as_ref());
127
128 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
129 assert_eq!(identifiable.id(), 123);
130 }
131
132 // 2. Using `FromReflect`
133 {
134 // If you know the type at compile time, you can use the `FromReflect` trait to convert the
135 // dynamic value into the concrete type directly.
136 let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap();
137 assert_eq!(value.id, 123);
138
139 // If you don't know the type at compile time, you can use the `ReflectFromReflect` type data
140 // to perform the conversion dynamically.
141 let reflect_from_reflect = registration
142 .data::<ReflectFromReflect>()
143 .expect("`ReflectFromReflect` should be registered");
144
145 let value: Box<dyn Reflect> = reflect_from_reflect
146 .from_reflect(deserialized.as_ref())
147 .unwrap();
148 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
149 assert_eq!(identifiable.id(), 123);
150 }
151
152 // Lastly, while dynamic types are commonly generated via reflection methods like
153 // `PartialReflect::to_dynamic` or via the reflection deserializers,
154 // you can also construct them manually.
155 let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
156
157 // This is useful when you just need to apply some subset of changes to a type.
158 let mut my_list: Vec<u32> = Vec::new();
159 my_list.apply(&my_dynamic_list);
160 assert_eq!(my_list, vec![1, 2, 3]);
161
162 // And if you want it to actually proxy a type, you can configure it to do that as well:
163 assert!(!my_dynamic_list
164 .as_partial_reflect()
165 .represents::<Vec<u32>>());
166 my_dynamic_list.set_represented_type(Some(<Vec<u32>>::type_info()));
167 assert!(my_dynamic_list
168 .as_partial_reflect()
169 .represents::<Vec<u32>>());
170
171 // ============================= REFERENCE ============================= //
172 // For reference, here are all the available dynamic types:
173
174 // 1. `DynamicTuple`
175 {
176 let mut dynamic_tuple = DynamicTuple::default();
177 dynamic_tuple.insert(1u32);
178 dynamic_tuple.insert(2u32);
179 dynamic_tuple.insert(3u32);
180
181 let mut my_tuple: (u32, u32, u32) = (0, 0, 0);
182 my_tuple.apply(&dynamic_tuple);
183 assert_eq!(my_tuple, (1, 2, 3));
184 }
185
186 // 2. `DynamicArray`
187 {
188 let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);
189
190 let mut my_array = [0u32; 3];
191 my_array.apply(&dynamic_array);
192 assert_eq!(my_array, [1, 2, 3]);
193 }
194
195 // 3. `DynamicList`
196 {
197 let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
198
199 let mut my_list: Vec<u32> = Vec::new();
200 my_list.apply(&dynamic_list);
201 assert_eq!(my_list, vec![1, 2, 3]);
202 }
203
204 // 4. `DynamicSet`
205 {
206 let mut dynamic_set = DynamicSet::from_iter(["x", "y", "z"]);
207 assert!(dynamic_set.contains(&"x"));
208
209 dynamic_set.remove(&"y");
210
211 let mut my_set: HashSet<&str> = HashSet::default();
212 my_set.apply(&dynamic_set);
213 assert_eq!(my_set, HashSet::from_iter(["x", "z"]));
214 }
215
216 // 5. `DynamicMap`
217 {
218 let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);
219
220 let mut my_map: HashMap<&str, u32> = HashMap::default();
221 my_map.apply(&dynamic_map);
222 assert_eq!(my_map.get("x"), Some(&1));
223 assert_eq!(my_map.get("y"), Some(&2));
224 assert_eq!(my_map.get("z"), Some(&3));
225 }
226
227 // 6. `DynamicStruct`
228 {
229 #[derive(Reflect, Default, Debug, PartialEq)]
230 struct MyStruct {
231 x: u32,
232 y: u32,
233 z: u32,
234 }
235
236 let mut dynamic_struct = DynamicStruct::default();
237 dynamic_struct.insert("x", 1u32);
238 dynamic_struct.insert("y", 2u32);
239 dynamic_struct.insert("z", 3u32);
240
241 let mut my_struct = MyStruct::default();
242 my_struct.apply(&dynamic_struct);
243 assert_eq!(my_struct, MyStruct { x: 1, y: 2, z: 3 });
244 }
245
246 // 7. `DynamicTupleStruct`
247 {
248 #[derive(Reflect, Default, Debug, PartialEq)]
249 struct MyTupleStruct(u32, u32, u32);
250
251 let mut dynamic_tuple_struct = DynamicTupleStruct::default();
252 dynamic_tuple_struct.insert(1u32);
253 dynamic_tuple_struct.insert(2u32);
254 dynamic_tuple_struct.insert(3u32);
255
256 let mut my_tuple_struct = MyTupleStruct::default();
257 my_tuple_struct.apply(&dynamic_tuple_struct);
258 assert_eq!(my_tuple_struct, MyTupleStruct(1, 2, 3));
259 }
260
261 // 8. `DynamicEnum`
262 {
263 #[derive(Reflect, Default, Debug, PartialEq)]
264 enum MyEnum {
265 #[default]
266 Empty,
267 Xyz(u32, u32, u32),
268 }
269
270 let mut values = DynamicTuple::default();
271 values.insert(1u32);
272 values.insert(2u32);
273 values.insert(3u32);
274
275 let dynamic_variant = DynamicVariant::Tuple(values);
276 let dynamic_enum = DynamicEnum::new("Xyz", dynamic_variant);
277
278 let mut my_enum = MyEnum::default();
279 my_enum.apply(&dynamic_enum);
280 assert_eq!(my_enum, MyEnum::Xyz(1, 2, 3));
281 }
282}Sourcepub fn try_downcast<T>(
self: Box<dyn PartialReflect>,
) -> Result<Box<T>, Box<dyn PartialReflect>>where
T: Any,
pub fn try_downcast<T>(
self: Box<dyn PartialReflect>,
) -> Result<Box<T>, Box<dyn PartialReflect>>where
T: Any,
Downcasts the value to type T, consuming the trait object.
If the underlying value does not implement Reflect
or is not of type T, returns Err(self).
For remote types, T should be the type itself rather than the wrapper type.
Sourcepub fn try_take<T>(
self: Box<dyn PartialReflect>,
) -> Result<T, Box<dyn PartialReflect>>where
T: Any,
pub fn try_take<T>(
self: Box<dyn PartialReflect>,
) -> Result<T, Box<dyn PartialReflect>>where
T: Any,
Downcasts the value to type T, unboxing and consuming the trait object.
If the underlying value does not implement Reflect
or is not of type T, returns Err(self).
For remote types, T should be the type itself rather than the wrapper type.
Examples found in repository?
19fn main() {
20 // There are times when it may be helpful to store a function away for later.
21 // In Rust, we can do this by storing either a function pointer or a function trait object.
22 // For example, say we wanted to store the following function:
23 fn add(left: i32, right: i32) -> i32 {
24 left + right
25 }
26
27 // We could store it as either of the following:
28 let fn_pointer: fn(i32, i32) -> i32 = add;
29 let fn_trait_object: Box<dyn Fn(i32, i32) -> i32> = Box::new(add);
30
31 // And we can call them like so:
32 let result = fn_pointer(2, 2);
33 assert_eq!(result, 4);
34 let result = fn_trait_object(2, 2);
35 assert_eq!(result, 4);
36
37 // However, you'll notice that we have to know the types of the arguments and return value at compile time.
38 // This means there's not really a way to store or call these functions dynamically at runtime.
39 // Luckily, Bevy's reflection crate comes with a set of tools for doing just that!
40 // We do this by first converting our function into the reflection-based `DynamicFunction` type
41 // using the `IntoFunction` trait.
42 let function: DynamicFunction<'static> = dbg!(add.into_function());
43
44 // This time, you'll notice that `DynamicFunction` doesn't take any information about the function's arguments or return value.
45 // This is because `DynamicFunction` checks the types of the arguments and return value at runtime.
46 // Now we can generate a list of arguments:
47 let args: ArgList = dbg!(ArgList::new().with_owned(2_i32).with_owned(2_i32));
48
49 // And finally, we can call the function.
50 // This returns a `Result` indicating whether the function was called successfully.
51 // For now, we'll just unwrap it to get our `Return` value,
52 // which is an enum containing the function's return value.
53 let return_value: Return = dbg!(function.call(args).unwrap());
54
55 // The `Return` value can be pattern matched or unwrapped to get the underlying reflection data.
56 // For the sake of brevity, we'll just unwrap it here and downcast it to the expected type of `i32`.
57 let value: Box<dyn PartialReflect> = return_value.unwrap_owned();
58 assert_eq!(value.try_take::<i32>().unwrap(), 4);
59
60 // The same can also be done for closures that capture references to their environment.
61 // Closures that capture their environment immutably can be converted into a `DynamicFunction`
62 // using the `IntoFunction` trait.
63 let minimum = 5;
64 let clamp = |value: i32| value.max(minimum);
65
66 let function: DynamicFunction = dbg!(clamp.into_function());
67 let args = dbg!(ArgList::new().with_owned(2_i32));
68 let return_value = dbg!(function.call(args).unwrap());
69 let value: Box<dyn PartialReflect> = return_value.unwrap_owned();
70 assert_eq!(value.try_take::<i32>().unwrap(), 5);
71
72 // We can also handle closures that capture their environment mutably
73 // using the `IntoFunctionMut` trait.
74 let mut count = 0;
75 let increment = |amount: i32| count += amount;
76
77 let closure: DynamicFunctionMut = dbg!(increment.into_function_mut());
78 let args = dbg!(ArgList::new().with_owned(5_i32));
79
80 // Because `DynamicFunctionMut` mutably borrows `total`,
81 // it will need to be dropped before `total` can be accessed again.
82 // This can be done manually with `drop(closure)` or by using the `DynamicFunctionMut::call_once` method.
83 dbg!(closure.call_once(args).unwrap());
84 assert_eq!(count, 5);
85
86 // Generic functions can also be converted into a `DynamicFunction`,
87 // however, they will need to be manually monomorphized first.
88 fn stringify<T: ToString>(value: T) -> String {
89 value.to_string()
90 }
91
92 // We have to manually specify the concrete generic type we want to use.
93 let function = stringify::<i32>.into_function();
94
95 let args = ArgList::new().with_owned(123_i32);
96 let return_value = function.call(args).unwrap();
97 let value: Box<dyn PartialReflect> = return_value.unwrap_owned();
98 assert_eq!(value.try_take::<String>().unwrap(), "123");
99
100 // To make things a little easier, we can also "overload" functions.
101 // This makes it so that a single `DynamicFunction` can represent multiple functions,
102 // and the correct one is chosen based on the types of the arguments.
103 // Each function overload must have a unique argument signature.
104 let function = stringify::<i32>
105 .into_function()
106 .with_overload(stringify::<f32>);
107
108 // Now our `function` accepts both `i32` and `f32` arguments.
109 let args = ArgList::new().with_owned(1.23_f32);
110 let return_value = function.call(args).unwrap();
111 let value: Box<dyn PartialReflect> = return_value.unwrap_owned();
112 assert_eq!(value.try_take::<String>().unwrap(), "1.23");
113
114 // Function overloading even allows us to have a variable number of arguments.
115 let function = (|| 0)
116 .into_function()
117 .with_overload(|a: i32| a)
118 .with_overload(|a: i32, b: i32| a + b)
119 .with_overload(|a: i32, b: i32, c: i32| a + b + c);
120
121 let args = ArgList::new()
122 .with_owned(1_i32)
123 .with_owned(2_i32)
124 .with_owned(3_i32);
125 let return_value = function.call(args).unwrap();
126 let value: Box<dyn PartialReflect> = return_value.unwrap_owned();
127 assert_eq!(value.try_take::<i32>().unwrap(), 6);
128
129 // As stated earlier, `IntoFunction` works for many kinds of simple functions.
130 // Functions with non-reflectable arguments or return values may not be able to be converted.
131 // Generic functions are also not supported (unless manually monomorphized like `foo::<i32>.into_function()`).
132 // Additionally, the lifetime of the return value is tied to the lifetime of the first argument.
133 // However, this means that many methods (i.e. functions with a `self` parameter) are also supported:
134 #[derive(Reflect, Default)]
135 struct Data {
136 value: String,
137 }
138
139 impl Data {
140 fn set_value(&mut self, value: String) {
141 self.value = value;
142 }
143
144 // Note that only `&'static str` implements `Reflect`.
145 // To get around this limitation we can use `&String` instead.
146 fn get_value(&self) -> &String {
147 &self.value
148 }
149 }
150
151 let mut data = Data::default();
152
153 let set_value = dbg!(Data::set_value.into_function());
154 let args = dbg!(ArgList::new().with_mut(&mut data)).with_owned(String::from("Hello, world!"));
155 dbg!(set_value.call(args).unwrap());
156 assert_eq!(data.value, "Hello, world!");
157
158 let get_value = dbg!(Data::get_value.into_function());
159 let args = dbg!(ArgList::new().with_ref(&data));
160 let return_value = dbg!(get_value.call(args).unwrap());
161 let value: &dyn PartialReflect = return_value.unwrap_ref();
162 assert_eq!(value.try_downcast_ref::<String>().unwrap(), "Hello, world!");
163
164 // For more complex use cases, you can always create a custom `DynamicFunction` manually.
165 // This is useful for functions that can't be converted via the `IntoFunction` trait.
166 // For example, this function doesn't implement `IntoFunction` due to the fact that
167 // the lifetime of the return value is not tied to the lifetime of the first argument.
168 fn get_or_insert(value: i32, container: &mut Option<i32>) -> &i32 {
169 if container.is_none() {
170 *container = Some(value);
171 }
172
173 container.as_ref().unwrap()
174 }
175
176 let get_or_insert_function = dbg!(DynamicFunction::new(
177 |mut args: ArgList| -> FunctionResult {
178 // The `ArgList` contains the arguments in the order they were pushed.
179 // The `DynamicFunction` will validate that the list contains
180 // exactly the number of arguments we expect.
181 // We can retrieve them out in order (note that this modifies the `ArgList`):
182 let value = args.take::<i32>()?;
183 let container = args.take::<&mut Option<i32>>()?;
184
185 // We could have also done the following to make use of type inference:
186 // let value = args.take_owned()?;
187 // let container = args.take_mut()?;
188
189 Ok(Return::Ref(get_or_insert(value, container)))
190 },
191 // Functions can be either anonymous or named.
192 // It's good practice, though, to try and name your functions whenever possible.
193 // This makes it easier to debug and is also required for function registration.
194 // We can either give it a custom name or use the function's type name as
195 // derived from `std::any::type_name_of_val`.
196 SignatureInfo::named(std::any::type_name_of_val(&get_or_insert))
197 // We can always change the name if needed.
198 // It's a good idea to also ensure that the name is unique,
199 // such as by using its type name or by prefixing it with your crate name.
200 .with_name("my_crate::get_or_insert")
201 // Since our function takes arguments, we should provide that argument information.
202 // This is used to validate arguments when calling the function.
203 // And it aids consumers of the function with their own validation and debugging.
204 // Arguments should be provided in the order they are defined in the function.
205 .with_arg::<i32>("value")
206 .with_arg::<&mut Option<i32>>("container")
207 // We can provide return information as well.
208 .with_return::<&i32>(),
209 ));
210
211 let mut container: Option<i32> = None;
212
213 let args = dbg!(ArgList::new().with_owned(5_i32).with_mut(&mut container));
214 let value = dbg!(get_or_insert_function.call(args).unwrap()).unwrap_ref();
215 assert_eq!(value.try_downcast_ref::<i32>(), Some(&5));
216
217 let args = dbg!(ArgList::new().with_owned(500_i32).with_mut(&mut container));
218 let value = dbg!(get_or_insert_function.call(args).unwrap()).unwrap_ref();
219 assert_eq!(value.try_downcast_ref::<i32>(), Some(&5));
220}Sourcepub fn try_downcast_ref<T>(&self) -> Option<&T>where
T: Any,
pub fn try_downcast_ref<T>(&self) -> Option<&T>where
T: Any,
Downcasts the value to type T by reference.
If the underlying value does not implement Reflect
or is not of type T, returns None.
For remote types, T should be the type itself rather than the wrapper type.
Examples found in repository?
49#[reflect(Hash, PartialEq, Clone)]
50pub struct E {
51 x: usize,
52}
53
54/// By default, deriving with Reflect assumes the type is either a "struct" or an "enum".
55///
56/// You can tell reflect to treat your type instead as an "opaque type" by using the `#[reflect(opaque)]`.
57/// It is generally a good idea to implement (and reflect) the `PartialEq` and `Clone` (optionally also `Serialize` and `Deserialize`)
58/// traits on opaque types to ensure that these values behave as expected when nested in other reflected types.
59#[derive(Reflect, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
60#[reflect(opaque)]
61#[reflect(PartialEqMore examples
55fn setup(type_registry: Res<AppTypeRegistry>) {
56 let mut value = Foo {
57 a: 1,
58 _ignored: NonReflectedValue { _a: 10 },
59 nested: Bar { b: 8 },
60 };
61
62 // You can set field values like this. The type must match exactly or this will fail.
63 *value.get_field_mut("a").unwrap() = 2usize;
64 assert_eq!(value.a, 2);
65 assert_eq!(*value.get_field::<usize>("a").unwrap(), 2);
66
67 // You can also get the `&dyn PartialReflect` value of a field like this
68 let field = value.field("a").unwrap();
69
70 // But values introspected via `PartialReflect` will not return `dyn Reflect` trait objects
71 // (even if the containing type does implement `Reflect`), so we need to convert them:
72 let fully_reflected_field = field.try_as_reflect().unwrap();
73
74 // Now, you can downcast your `Reflect` value like this:
75 assert_eq!(*fully_reflected_field.downcast_ref::<usize>().unwrap(), 2);
76
77 // For this specific case, we also support the shortcut `try_downcast_ref`:
78 assert_eq!(*field.try_downcast_ref::<usize>().unwrap(), 2);
79
80 // `DynamicStruct` also implements the `Struct` and `Reflect` traits.
81 let mut patch = DynamicStruct::default();
82 patch.insert("a", 4usize);
83
84 // You can "apply" Reflect implementations on top of other Reflect implementations.
85 // This will only set fields with the same name, and it will fail if the types don't match.
86 // You can use this to "patch" your types with new values.
87 value.apply(&patch);
88 assert_eq!(value.a, 4);
89
90 let type_registry = type_registry.read();
91 // By default, all derived `Reflect` types can be Serialized using serde. No need to derive
92 // Serialize!
93 let serializer = ReflectSerializer::new(&value, &type_registry);
94 let ron_string =
95 ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
96 info!("{}\n", ron_string);
97
98 // Dynamic properties can be deserialized
99 let reflect_deserializer = ReflectDeserializer::new(&type_registry);
100 let mut deserializer = ron::de::Deserializer::from_str(&ron_string).unwrap();
101 let reflect_value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
102
103 // Deserializing returns a `Box<dyn PartialReflect>` value.
104 // Generally, deserializing a value will return the "dynamic" variant of a type.
105 // For example, deserializing a struct will return the DynamicStruct type.
106 // "Opaque types" will be deserialized as themselves.
107 assert_eq!(
108 reflect_value.reflect_type_path(),
109 DynamicStruct::type_path(),
110 );
111
112 // Reflect has its own `partial_eq` implementation, named `reflect_partial_eq`. This behaves
113 // like normal `partial_eq`, but it treats "dynamic" and "non-dynamic" types the same. The
114 // `Foo` struct and deserialized `DynamicStruct` are considered equal for this reason:
115 assert!(reflect_value.reflect_partial_eq(&value).unwrap());
116
117 // By "patching" `Foo` with the deserialized DynamicStruct, we can "Deserialize" Foo.
118 // This means we can serialize and deserialize with a single `Reflect` derive!
119 value.apply(&*reflect_value);
120}19fn main() {
20 // There are times when it may be helpful to store a function away for later.
21 // In Rust, we can do this by storing either a function pointer or a function trait object.
22 // For example, say we wanted to store the following function:
23 fn add(left: i32, right: i32) -> i32 {
24 left + right
25 }
26
27 // We could store it as either of the following:
28 let fn_pointer: fn(i32, i32) -> i32 = add;
29 let fn_trait_object: Box<dyn Fn(i32, i32) -> i32> = Box::new(add);
30
31 // And we can call them like so:
32 let result = fn_pointer(2, 2);
33 assert_eq!(result, 4);
34 let result = fn_trait_object(2, 2);
35 assert_eq!(result, 4);
36
37 // However, you'll notice that we have to know the types of the arguments and return value at compile time.
38 // This means there's not really a way to store or call these functions dynamically at runtime.
39 // Luckily, Bevy's reflection crate comes with a set of tools for doing just that!
40 // We do this by first converting our function into the reflection-based `DynamicFunction` type
41 // using the `IntoFunction` trait.
42 let function: DynamicFunction<'static> = dbg!(add.into_function());
43
44 // This time, you'll notice that `DynamicFunction` doesn't take any information about the function's arguments or return value.
45 // This is because `DynamicFunction` checks the types of the arguments and return value at runtime.
46 // Now we can generate a list of arguments:
47 let args: ArgList = dbg!(ArgList::new().with_owned(2_i32).with_owned(2_i32));
48
49 // And finally, we can call the function.
50 // This returns a `Result` indicating whether the function was called successfully.
51 // For now, we'll just unwrap it to get our `Return` value,
52 // which is an enum containing the function's return value.
53 let return_value: Return = dbg!(function.call(args).unwrap());
54
55 // The `Return` value can be pattern matched or unwrapped to get the underlying reflection data.
56 // For the sake of brevity, we'll just unwrap it here and downcast it to the expected type of `i32`.
57 let value: Box<dyn PartialReflect> = return_value.unwrap_owned();
58 assert_eq!(value.try_take::<i32>().unwrap(), 4);
59
60 // The same can also be done for closures that capture references to their environment.
61 // Closures that capture their environment immutably can be converted into a `DynamicFunction`
62 // using the `IntoFunction` trait.
63 let minimum = 5;
64 let clamp = |value: i32| value.max(minimum);
65
66 let function: DynamicFunction = dbg!(clamp.into_function());
67 let args = dbg!(ArgList::new().with_owned(2_i32));
68 let return_value = dbg!(function.call(args).unwrap());
69 let value: Box<dyn PartialReflect> = return_value.unwrap_owned();
70 assert_eq!(value.try_take::<i32>().unwrap(), 5);
71
72 // We can also handle closures that capture their environment mutably
73 // using the `IntoFunctionMut` trait.
74 let mut count = 0;
75 let increment = |amount: i32| count += amount;
76
77 let closure: DynamicFunctionMut = dbg!(increment.into_function_mut());
78 let args = dbg!(ArgList::new().with_owned(5_i32));
79
80 // Because `DynamicFunctionMut` mutably borrows `total`,
81 // it will need to be dropped before `total` can be accessed again.
82 // This can be done manually with `drop(closure)` or by using the `DynamicFunctionMut::call_once` method.
83 dbg!(closure.call_once(args).unwrap());
84 assert_eq!(count, 5);
85
86 // Generic functions can also be converted into a `DynamicFunction`,
87 // however, they will need to be manually monomorphized first.
88 fn stringify<T: ToString>(value: T) -> String {
89 value.to_string()
90 }
91
92 // We have to manually specify the concrete generic type we want to use.
93 let function = stringify::<i32>.into_function();
94
95 let args = ArgList::new().with_owned(123_i32);
96 let return_value = function.call(args).unwrap();
97 let value: Box<dyn PartialReflect> = return_value.unwrap_owned();
98 assert_eq!(value.try_take::<String>().unwrap(), "123");
99
100 // To make things a little easier, we can also "overload" functions.
101 // This makes it so that a single `DynamicFunction` can represent multiple functions,
102 // and the correct one is chosen based on the types of the arguments.
103 // Each function overload must have a unique argument signature.
104 let function = stringify::<i32>
105 .into_function()
106 .with_overload(stringify::<f32>);
107
108 // Now our `function` accepts both `i32` and `f32` arguments.
109 let args = ArgList::new().with_owned(1.23_f32);
110 let return_value = function.call(args).unwrap();
111 let value: Box<dyn PartialReflect> = return_value.unwrap_owned();
112 assert_eq!(value.try_take::<String>().unwrap(), "1.23");
113
114 // Function overloading even allows us to have a variable number of arguments.
115 let function = (|| 0)
116 .into_function()
117 .with_overload(|a: i32| a)
118 .with_overload(|a: i32, b: i32| a + b)
119 .with_overload(|a: i32, b: i32, c: i32| a + b + c);
120
121 let args = ArgList::new()
122 .with_owned(1_i32)
123 .with_owned(2_i32)
124 .with_owned(3_i32);
125 let return_value = function.call(args).unwrap();
126 let value: Box<dyn PartialReflect> = return_value.unwrap_owned();
127 assert_eq!(value.try_take::<i32>().unwrap(), 6);
128
129 // As stated earlier, `IntoFunction` works for many kinds of simple functions.
130 // Functions with non-reflectable arguments or return values may not be able to be converted.
131 // Generic functions are also not supported (unless manually monomorphized like `foo::<i32>.into_function()`).
132 // Additionally, the lifetime of the return value is tied to the lifetime of the first argument.
133 // However, this means that many methods (i.e. functions with a `self` parameter) are also supported:
134 #[derive(Reflect, Default)]
135 struct Data {
136 value: String,
137 }
138
139 impl Data {
140 fn set_value(&mut self, value: String) {
141 self.value = value;
142 }
143
144 // Note that only `&'static str` implements `Reflect`.
145 // To get around this limitation we can use `&String` instead.
146 fn get_value(&self) -> &String {
147 &self.value
148 }
149 }
150
151 let mut data = Data::default();
152
153 let set_value = dbg!(Data::set_value.into_function());
154 let args = dbg!(ArgList::new().with_mut(&mut data)).with_owned(String::from("Hello, world!"));
155 dbg!(set_value.call(args).unwrap());
156 assert_eq!(data.value, "Hello, world!");
157
158 let get_value = dbg!(Data::get_value.into_function());
159 let args = dbg!(ArgList::new().with_ref(&data));
160 let return_value = dbg!(get_value.call(args).unwrap());
161 let value: &dyn PartialReflect = return_value.unwrap_ref();
162 assert_eq!(value.try_downcast_ref::<String>().unwrap(), "Hello, world!");
163
164 // For more complex use cases, you can always create a custom `DynamicFunction` manually.
165 // This is useful for functions that can't be converted via the `IntoFunction` trait.
166 // For example, this function doesn't implement `IntoFunction` due to the fact that
167 // the lifetime of the return value is not tied to the lifetime of the first argument.
168 fn get_or_insert(value: i32, container: &mut Option<i32>) -> &i32 {
169 if container.is_none() {
170 *container = Some(value);
171 }
172
173 container.as_ref().unwrap()
174 }
175
176 let get_or_insert_function = dbg!(DynamicFunction::new(
177 |mut args: ArgList| -> FunctionResult {
178 // The `ArgList` contains the arguments in the order they were pushed.
179 // The `DynamicFunction` will validate that the list contains
180 // exactly the number of arguments we expect.
181 // We can retrieve them out in order (note that this modifies the `ArgList`):
182 let value = args.take::<i32>()?;
183 let container = args.take::<&mut Option<i32>>()?;
184
185 // We could have also done the following to make use of type inference:
186 // let value = args.take_owned()?;
187 // let container = args.take_mut()?;
188
189 Ok(Return::Ref(get_or_insert(value, container)))
190 },
191 // Functions can be either anonymous or named.
192 // It's good practice, though, to try and name your functions whenever possible.
193 // This makes it easier to debug and is also required for function registration.
194 // We can either give it a custom name or use the function's type name as
195 // derived from `std::any::type_name_of_val`.
196 SignatureInfo::named(std::any::type_name_of_val(&get_or_insert))
197 // We can always change the name if needed.
198 // It's a good idea to also ensure that the name is unique,
199 // such as by using its type name or by prefixing it with your crate name.
200 .with_name("my_crate::get_or_insert")
201 // Since our function takes arguments, we should provide that argument information.
202 // This is used to validate arguments when calling the function.
203 // And it aids consumers of the function with their own validation and debugging.
204 // Arguments should be provided in the order they are defined in the function.
205 .with_arg::<i32>("value")
206 .with_arg::<&mut Option<i32>>("container")
207 // We can provide return information as well.
208 .with_return::<&i32>(),
209 ));
210
211 let mut container: Option<i32> = None;
212
213 let args = dbg!(ArgList::new().with_owned(5_i32).with_mut(&mut container));
214 let value = dbg!(get_or_insert_function.call(args).unwrap()).unwrap_ref();
215 assert_eq!(value.try_downcast_ref::<i32>(), Some(&5));
216
217 let args = dbg!(ArgList::new().with_owned(500_i32).with_mut(&mut container));
218 let value = dbg!(get_or_insert_function.call(args).unwrap()).unwrap_ref();
219 assert_eq!(value.try_downcast_ref::<i32>(), Some(&5));
220}20fn main() {
21 #[derive(Reflect, Default, PartialEq, Debug)]
22 #[reflect(Identifiable, Default)]
23 struct Player {
24 id: u32,
25 }
26
27 #[reflect_trait]
28 trait Identifiable {
29 fn id(&self) -> u32;
30 }
31
32 impl Identifiable for Player {
33 fn id(&self) -> u32 {
34 self.id
35 }
36 }
37
38 // Normally, when instantiating a type, you get back exactly that type.
39 // This is because the type is known at compile time.
40 // We call this the "concrete" or "canonical" type.
41 let player: Player = Player { id: 123 };
42
43 // When working with reflected types, however, we often "erase" this type information
44 // using the `Reflect` trait object.
45 // This trait object also gives us access to all the methods in the `PartialReflect` trait too.
46 // The underlying type is still the same (in this case, `Player`),
47 // but now we've hidden that information from the compiler.
48 let reflected: Box<dyn Reflect> = Box::new(player);
49
50 // Because it's the same type under the hood, we can still downcast it back to the original type.
51 assert!(reflected.downcast_ref::<Player>().is_some());
52
53 // We can attempt to clone our value using `PartialReflect::reflect_clone`.
54 // This will recursively call `PartialReflect::reflect_clone` on all fields of the type.
55 // Or, if we had registered `ReflectClone` using `#[reflect(Clone)]`, it would simply call `Clone::clone` directly.
56 let cloned: Box<dyn Reflect> = reflected.reflect_clone().unwrap();
57 assert_eq!(cloned.downcast_ref::<Player>(), Some(&Player { id: 123 }));
58
59 // Another way we can "clone" our data is by converting it to a dynamic type.
60 // Notice here we bind it as a `dyn PartialReflect` instead of `dyn Reflect`.
61 // This is because it returns a dynamic type that simply represents the original type.
62 // In this case, because `Player` is a struct, it will return a `DynamicStruct`.
63 let dynamic: Box<dyn PartialReflect> = reflected.to_dynamic();
64 assert!(dynamic.is_dynamic());
65
66 // And if we try to convert it back to a `dyn Reflect` trait object, we'll get `None`.
67 // Dynamic types cannot be directly cast to `dyn Reflect` trait objects.
68 assert!(dynamic.try_as_reflect().is_none());
69
70 // Generally dynamic types are used to represent (or "proxy") the original type,
71 // so that we can continue to access its fields and overall structure.
72 let dynamic_ref = dynamic.reflect_ref().as_struct().unwrap();
73 let id = dynamic_ref.field("id").unwrap().try_downcast_ref::<u32>();
74 assert_eq!(id, Some(&123));
75
76 // It also enables us to create a representation of a type without having compile-time
77 // access to the actual type. This is how the reflection deserializers work.
78 // They generally can't know how to construct a type ahead of time,
79 // so they instead build and return these dynamic representations.
80 let input = "(id: 123)";
81 let mut registry = TypeRegistry::default();
82 registry.register::<Player>();
83 let registration = registry.get(std::any::TypeId::of::<Player>()).unwrap();
84 let deserialized = TypedReflectDeserializer::new(registration, ®istry)
85 .deserialize(&mut ron::Deserializer::from_str(input).unwrap())
86 .unwrap();
87
88 // Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`.
89 assert!(deserialized.represents::<Player>());
90
91 // And while this does allow us to access the fields and structure of the type,
92 // there may be instances where we need the actual type.
93 // For example, if we want to convert our `dyn Reflect` into a `dyn Identifiable`,
94 // we can't use the `DynamicStruct` proxy.
95 let reflect_identifiable = registration
96 .data::<ReflectIdentifiable>()
97 .expect("`ReflectIdentifiable` should be registered");
98
99 // Trying to access the registry with our `deserialized` will give a compile error
100 // since it doesn't implement `Reflect`, only `PartialReflect`.
101 // Similarly, trying to force the operation will fail.
102 // This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`.
103 assert!(deserialized
104 .try_as_reflect()
105 .and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj))
106 .is_none());
107
108 // So how can we go from a dynamic type to a concrete type?
109 // There are two ways:
110
111 // 1. Using `PartialReflect::apply`.
112 {
113 // If you know the type at compile time, you can construct a new value and apply the dynamic
114 // value to it.
115 let mut value = Player::default();
116 value.apply(deserialized.as_ref());
117 assert_eq!(value.id, 123);
118
119 // If you don't know the type at compile time, you need a dynamic way of constructing
120 // an instance of the type. One such way is to use the `ReflectDefault` type data.
121 let reflect_default = registration
122 .data::<ReflectDefault>()
123 .expect("`ReflectDefault` should be registered");
124
125 let mut value: Box<dyn Reflect> = reflect_default.default();
126 value.apply(deserialized.as_ref());
127
128 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
129 assert_eq!(identifiable.id(), 123);
130 }
131
132 // 2. Using `FromReflect`
133 {
134 // If you know the type at compile time, you can use the `FromReflect` trait to convert the
135 // dynamic value into the concrete type directly.
136 let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap();
137 assert_eq!(value.id, 123);
138
139 // If you don't know the type at compile time, you can use the `ReflectFromReflect` type data
140 // to perform the conversion dynamically.
141 let reflect_from_reflect = registration
142 .data::<ReflectFromReflect>()
143 .expect("`ReflectFromReflect` should be registered");
144
145 let value: Box<dyn Reflect> = reflect_from_reflect
146 .from_reflect(deserialized.as_ref())
147 .unwrap();
148 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
149 assert_eq!(identifiable.id(), 123);
150 }
151
152 // Lastly, while dynamic types are commonly generated via reflection methods like
153 // `PartialReflect::to_dynamic` or via the reflection deserializers,
154 // you can also construct them manually.
155 let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
156
157 // This is useful when you just need to apply some subset of changes to a type.
158 let mut my_list: Vec<u32> = Vec::new();
159 my_list.apply(&my_dynamic_list);
160 assert_eq!(my_list, vec![1, 2, 3]);
161
162 // And if you want it to actually proxy a type, you can configure it to do that as well:
163 assert!(!my_dynamic_list
164 .as_partial_reflect()
165 .represents::<Vec<u32>>());
166 my_dynamic_list.set_represented_type(Some(<Vec<u32>>::type_info()));
167 assert!(my_dynamic_list
168 .as_partial_reflect()
169 .represents::<Vec<u32>>());
170
171 // ============================= REFERENCE ============================= //
172 // For reference, here are all the available dynamic types:
173
174 // 1. `DynamicTuple`
175 {
176 let mut dynamic_tuple = DynamicTuple::default();
177 dynamic_tuple.insert(1u32);
178 dynamic_tuple.insert(2u32);
179 dynamic_tuple.insert(3u32);
180
181 let mut my_tuple: (u32, u32, u32) = (0, 0, 0);
182 my_tuple.apply(&dynamic_tuple);
183 assert_eq!(my_tuple, (1, 2, 3));
184 }
185
186 // 2. `DynamicArray`
187 {
188 let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);
189
190 let mut my_array = [0u32; 3];
191 my_array.apply(&dynamic_array);
192 assert_eq!(my_array, [1, 2, 3]);
193 }
194
195 // 3. `DynamicList`
196 {
197 let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
198
199 let mut my_list: Vec<u32> = Vec::new();
200 my_list.apply(&dynamic_list);
201 assert_eq!(my_list, vec![1, 2, 3]);
202 }
203
204 // 4. `DynamicSet`
205 {
206 let mut dynamic_set = DynamicSet::from_iter(["x", "y", "z"]);
207 assert!(dynamic_set.contains(&"x"));
208
209 dynamic_set.remove(&"y");
210
211 let mut my_set: HashSet<&str> = HashSet::default();
212 my_set.apply(&dynamic_set);
213 assert_eq!(my_set, HashSet::from_iter(["x", "z"]));
214 }
215
216 // 5. `DynamicMap`
217 {
218 let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);
219
220 let mut my_map: HashMap<&str, u32> = HashMap::default();
221 my_map.apply(&dynamic_map);
222 assert_eq!(my_map.get("x"), Some(&1));
223 assert_eq!(my_map.get("y"), Some(&2));
224 assert_eq!(my_map.get("z"), Some(&3));
225 }
226
227 // 6. `DynamicStruct`
228 {
229 #[derive(Reflect, Default, Debug, PartialEq)]
230 struct MyStruct {
231 x: u32,
232 y: u32,
233 z: u32,
234 }
235
236 let mut dynamic_struct = DynamicStruct::default();
237 dynamic_struct.insert("x", 1u32);
238 dynamic_struct.insert("y", 2u32);
239 dynamic_struct.insert("z", 3u32);
240
241 let mut my_struct = MyStruct::default();
242 my_struct.apply(&dynamic_struct);
243 assert_eq!(my_struct, MyStruct { x: 1, y: 2, z: 3 });
244 }
245
246 // 7. `DynamicTupleStruct`
247 {
248 #[derive(Reflect, Default, Debug, PartialEq)]
249 struct MyTupleStruct(u32, u32, u32);
250
251 let mut dynamic_tuple_struct = DynamicTupleStruct::default();
252 dynamic_tuple_struct.insert(1u32);
253 dynamic_tuple_struct.insert(2u32);
254 dynamic_tuple_struct.insert(3u32);
255
256 let mut my_tuple_struct = MyTupleStruct::default();
257 my_tuple_struct.apply(&dynamic_tuple_struct);
258 assert_eq!(my_tuple_struct, MyTupleStruct(1, 2, 3));
259 }
260
261 // 8. `DynamicEnum`
262 {
263 #[derive(Reflect, Default, Debug, PartialEq)]
264 enum MyEnum {
265 #[default]
266 Empty,
267 Xyz(u32, u32, u32),
268 }
269
270 let mut values = DynamicTuple::default();
271 values.insert(1u32);
272 values.insert(2u32);
273 values.insert(3u32);
274
275 let dynamic_variant = DynamicVariant::Tuple(values);
276 let dynamic_enum = DynamicEnum::new("Xyz", dynamic_variant);
277
278 let mut my_enum = MyEnum::default();
279 my_enum.apply(&dynamic_enum);
280 assert_eq!(my_enum, MyEnum::Xyz(1, 2, 3));
281 }
282}Trait Implementations§
Source§impl Debug for dyn PartialReflect
impl Debug for dyn PartialReflect
Source§impl FromIterator<Box<dyn PartialReflect>> for DynamicArray
impl FromIterator<Box<dyn PartialReflect>> for DynamicArray
Source§fn from_iter<I>(values: I) -> DynamicArray
fn from_iter<I>(values: I) -> DynamicArray
Source§impl FromIterator<Box<dyn PartialReflect>> for DynamicList
impl FromIterator<Box<dyn PartialReflect>> for DynamicList
Source§fn from_iter<I>(values: I) -> DynamicList
fn from_iter<I>(values: I) -> DynamicList
Source§impl FromIterator<Box<dyn PartialReflect>> for DynamicSet
impl FromIterator<Box<dyn PartialReflect>> for DynamicSet
Source§fn from_iter<I>(values: I) -> DynamicSet
fn from_iter<I>(values: I) -> DynamicSet
Source§impl FromIterator<Box<dyn PartialReflect>> for DynamicTuple
impl FromIterator<Box<dyn PartialReflect>> for DynamicTuple
Source§fn from_iter<I>(fields: I) -> DynamicTuple
fn from_iter<I>(fields: I) -> DynamicTuple
Source§impl FromIterator<Box<dyn PartialReflect>> for DynamicTupleStruct
impl FromIterator<Box<dyn PartialReflect>> for DynamicTupleStruct
Source§fn from_iter<I>(fields: I) -> DynamicTupleStruct
fn from_iter<I>(fields: I) -> DynamicTupleStruct
Source§impl TypePath for dyn PartialReflect
impl TypePath for dyn PartialReflect
Source§fn type_path() -> &'static str
fn type_path() -> &'static str
Source§fn short_type_path() -> &'static str
fn short_type_path() -> &'static str
Source§fn type_ident() -> Option<&'static str>
fn type_ident() -> Option<&'static str>
Source§fn crate_name() -> Option<&'static str>
fn crate_name() -> Option<&'static str>
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".