pub trait PartialReflect:
DynamicTypePath
+ Send
+ Sync
+ 'static {
Show 20 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 clone_value(&self) -> Box<dyn PartialReflect> { ... }
fn to_dynamic(&self) -> Box<dyn PartialReflect> { ... }
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> { ... }
fn reflect_hash(&self) -> Option<u64> { ... }
fn reflect_partial_eq(
&self,
_value: &(dyn PartialReflect + 'static),
) -> Option<bool> { ... }
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 a type implements an introspection subtrait, then the semantics of this method are as follows:
- If
T
is aStruct
, then the value of each named field ofvalue
is applied to the corresponding named field ofself
. Fields which are not present in both structs are ignored. - If
T
is aTupleStruct
orTuple
, 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
T
is anEnum
, then the variant ofself
isupdated
to match the variant ofvalue
. The corresponding fields of that variant are applied fromvalue
ontoself
. Fields which are not present in both values are ignored. - If
T
is aList
orArray
, then each element ofvalue
is applied to the corresponding element ofself
. Up toself.len()
items are applied, and excess elements invalue
are appended toself
. - If
T
is 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 inself
are inserted. - If
T
is none of these, thenvalue
is downcast toT
, cloned, and assigned toself
.
Note that Reflect
must be implemented manually for List
s and
Map
s 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 and maps, use the
list_apply
and map_apply
helper functions when implementing this method.
§Panics
Derived implementations of this method will panic:
- If the type of
value
is not of the same kind asT
(e.g. ifT
is aList
, whilevalue
is aStruct
). - If
T
is any complex type and the corresponding fields or elements ofself
andvalue
are not of the same type. - If
T
is an opaque type andself
cannot be downcast toT
Examples found in repository?
56fn setup(type_registry: Res<AppTypeRegistry>) {
57 let mut value = Foo {
58 a: 1,
59 _ignored: NonReflectedValue { _a: 10 },
60 nested: Bar { b: 8 },
61 };
62
63 // You can set field values like this. The type must match exactly or this will fail.
64 *value.get_field_mut("a").unwrap() = 2usize;
65 assert_eq!(value.a, 2);
66 assert_eq!(*value.get_field::<usize>("a").unwrap(), 2);
67
68 // You can also get the `&dyn PartialReflect` value of a field like this
69 let field = value.field("a").unwrap();
70
71 // But values introspected via `PartialReflect` will not return `dyn Reflect` trait objects
72 // (even if the containing type does implement `Reflect`), so we need to convert them:
73 let fully_reflected_field = field.try_as_reflect().unwrap();
74
75 // Now, you can downcast your `Reflect` value like this:
76 assert_eq!(*fully_reflected_field.downcast_ref::<usize>().unwrap(), 2);
77
78 // For this specific case, we also support the shortcut `try_downcast_ref`:
79 assert_eq!(*field.try_downcast_ref::<usize>().unwrap(), 2);
80
81 // `DynamicStruct` also implements the `Struct` and `Reflect` traits.
82 let mut patch = DynamicStruct::default();
83 patch.insert("a", 4usize);
84
85 // You can "apply" Reflect implementations on top of other Reflect implementations.
86 // This will only set fields with the same name, and it will fail if the types don't match.
87 // You can use this to "patch" your types with new values.
88 value.apply(&patch);
89 assert_eq!(value.a, 4);
90
91 let type_registry = type_registry.read();
92 // By default, all derived `Reflect` types can be Serialized using serde. No need to derive
93 // Serialize!
94 let serializer = ReflectSerializer::new(&value, &type_registry);
95 let ron_string =
96 ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
97 info!("{}\n", ron_string);
98
99 // Dynamic properties can be deserialized
100 let reflect_deserializer = ReflectDeserializer::new(&type_registry);
101 let mut deserializer = ron::de::Deserializer::from_str(&ron_string).unwrap();
102 let reflect_value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
103
104 // Deserializing returns a `Box<dyn PartialReflect>` value.
105 // Generally, deserializing a value will return the "dynamic" variant of a type.
106 // For example, deserializing a struct will return the DynamicStruct type.
107 // "Opaque types" will be deserialized as themselves.
108 assert_eq!(
109 reflect_value.reflect_type_path(),
110 DynamicStruct::type_path(),
111 );
112
113 // Reflect has its own `partial_eq` implementation, named `reflect_partial_eq`. This behaves
114 // like normal `partial_eq`, but it treats "dynamic" and "non-dynamic" types the same. The
115 // `Foo` struct and deserialized `DynamicStruct` are considered equal for this reason:
116 assert!(reflect_value.reflect_partial_eq(&value).unwrap());
117
118 // By "patching" `Foo` with the deserialized DynamicStruct, we can "Deserialize" Foo.
119 // This means we can serialize and deserialize with a single `Reflect` derive!
120 value.apply(&*reflect_value);
121}
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}
12fn main() {
13 #[derive(Reflect, Default, PartialEq, Debug)]
14 #[reflect(Identifiable, Default)]
15 struct Player {
16 id: u32,
17 }
18
19 #[reflect_trait]
20 trait Identifiable {
21 fn id(&self) -> u32;
22 }
23
24 impl Identifiable for Player {
25 fn id(&self) -> u32 {
26 self.id
27 }
28 }
29
30 // Normally, when instantiating a type, you get back exactly that type.
31 // This is because the type is known at compile time.
32 // We call this the "concrete" or "canonical" type.
33 let player: Player = Player { id: 123 };
34
35 // When working with reflected types, however, we often "erase" this type information
36 // using the `Reflect` trait object.
37 // This trait object also gives us access to all the methods in the `PartialReflect` trait too.
38 // The underlying type is still the same (in this case, `Player`),
39 // but now we've hidden that information from the compiler.
40 let reflected: Box<dyn Reflect> = Box::new(player);
41
42 // Because it's the same type under the hood, we can still downcast it back to the original type.
43 assert!(reflected.downcast_ref::<Player>().is_some());
44
45 // We can attempt to clone our value using `PartialReflect::reflect_clone`.
46 // This will recursively call `PartialReflect::reflect_clone` on all fields of the type.
47 // Or, if we had registered `ReflectClone` using `#[reflect(Clone)]`, it would simply call `Clone::clone` directly.
48 let cloned: Box<dyn Reflect> = reflected.reflect_clone().unwrap();
49 assert_eq!(cloned.downcast_ref::<Player>(), Some(&Player { id: 123 }));
50
51 // Another way we can "clone" our data is by converting it to a dynamic type.
52 // Notice here we bind it as a `dyn PartialReflect` instead of `dyn Reflect`.
53 // This is because it returns a dynamic type that simply represents the original type.
54 // In this case, because `Player` is a struct, it will return a `DynamicStruct`.
55 let dynamic: Box<dyn PartialReflect> = reflected.to_dynamic();
56 assert!(dynamic.is_dynamic());
57
58 // And if we try to convert it back to a `dyn Reflect` trait object, we'll get `None`.
59 // Dynamic types cannot be directly cast to `dyn Reflect` trait objects.
60 assert!(dynamic.try_as_reflect().is_none());
61
62 // Generally dynamic types are used to represent (or "proxy") the original type,
63 // so that we can continue to access its fields and overall structure.
64 let dynamic_ref = dynamic.reflect_ref().as_struct().unwrap();
65 let id = dynamic_ref.field("id").unwrap().try_downcast_ref::<u32>();
66 assert_eq!(id, Some(&123));
67
68 // It also enables us to create a representation of a type without having compile-time
69 // access to the actual type. This is how the reflection deserializers work.
70 // They generally can't know how to construct a type ahead of time,
71 // so they instead build and return these dynamic representations.
72 let input = "(id: 123)";
73 let mut registry = TypeRegistry::default();
74 registry.register::<Player>();
75 let registration = registry.get(std::any::TypeId::of::<Player>()).unwrap();
76 let deserialized = TypedReflectDeserializer::new(registration, ®istry)
77 .deserialize(&mut ron::Deserializer::from_str(input).unwrap())
78 .unwrap();
79
80 // Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`.
81 assert!(deserialized.represents::<Player>());
82
83 // And while this does allow us to access the fields and structure of the type,
84 // there may be instances where we need the actual type.
85 // For example, if we want to convert our `dyn Reflect` into a `dyn Identifiable`,
86 // we can't use the `DynamicStruct` proxy.
87 let reflect_identifiable = registration
88 .data::<ReflectIdentifiable>()
89 .expect("`ReflectIdentifiable` should be registered");
90
91 // Trying to access the registry with our `deserialized` will give a compile error
92 // since it doesn't implement `Reflect`, only `PartialReflect`.
93 // Similarly, trying to force the operation will fail.
94 // This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`.
95 assert!(deserialized
96 .try_as_reflect()
97 .and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj))
98 .is_none());
99
100 // So how can we go from a dynamic type to a concrete type?
101 // There are two ways:
102
103 // 1. Using `PartialReflect::apply`.
104 {
105 // If you know the type at compile time, you can construct a new value and apply the dynamic
106 // value to it.
107 let mut value = Player::default();
108 value.apply(deserialized.as_ref());
109 assert_eq!(value.id, 123);
110
111 // If you don't know the type at compile time, you need a dynamic way of constructing
112 // an instance of the type. One such way is to use the `ReflectDefault` type data.
113 let reflect_default = registration
114 .data::<ReflectDefault>()
115 .expect("`ReflectDefault` should be registered");
116
117 let mut value: Box<dyn Reflect> = reflect_default.default();
118 value.apply(deserialized.as_ref());
119
120 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
121 assert_eq!(identifiable.id(), 123);
122 }
123
124 // 2. Using `FromReflect`
125 {
126 // If you know the type at compile time, you can use the `FromReflect` trait to convert the
127 // dynamic value into the concrete type directly.
128 let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap();
129 assert_eq!(value.id, 123);
130
131 // If you don't know the type at compile time, you can use the `ReflectFromReflect` type data
132 // to perform the conversion dynamically.
133 let reflect_from_reflect = registration
134 .data::<ReflectFromReflect>()
135 .expect("`ReflectFromReflect` should be registered");
136
137 let value: Box<dyn Reflect> = reflect_from_reflect
138 .from_reflect(deserialized.as_ref())
139 .unwrap();
140 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
141 assert_eq!(identifiable.id(), 123);
142 }
143
144 // Lastly, while dynamic types are commonly generated via reflection methods like
145 // `PartialReflect::to_dynamic` or via the reflection deserializers,
146 // you can also construct them manually.
147 let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
148
149 // This is useful when you just need to apply some subset of changes to a type.
150 let mut my_list: Vec<u32> = Vec::new();
151 my_list.apply(&my_dynamic_list);
152 assert_eq!(my_list, vec![1, 2, 3]);
153
154 // And if you want it to actually proxy a type, you can configure it to do that as well:
155 assert!(!my_dynamic_list
156 .as_partial_reflect()
157 .represents::<Vec<u32>>());
158 my_dynamic_list.set_represented_type(Some(<Vec<u32>>::type_info()));
159 assert!(my_dynamic_list
160 .as_partial_reflect()
161 .represents::<Vec<u32>>());
162
163 // ============================= REFERENCE ============================= //
164 // For reference, here are all the available dynamic types:
165
166 // 1. `DynamicTuple`
167 {
168 let mut dynamic_tuple = DynamicTuple::default();
169 dynamic_tuple.insert(1u32);
170 dynamic_tuple.insert(2u32);
171 dynamic_tuple.insert(3u32);
172
173 let mut my_tuple: (u32, u32, u32) = (0, 0, 0);
174 my_tuple.apply(&dynamic_tuple);
175 assert_eq!(my_tuple, (1, 2, 3));
176 }
177
178 // 2. `DynamicArray`
179 {
180 let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);
181
182 let mut my_array = [0u32; 3];
183 my_array.apply(&dynamic_array);
184 assert_eq!(my_array, [1, 2, 3]);
185 }
186
187 // 3. `DynamicList`
188 {
189 let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
190
191 let mut my_list: Vec<u32> = Vec::new();
192 my_list.apply(&dynamic_list);
193 assert_eq!(my_list, vec![1, 2, 3]);
194 }
195
196 // 4. `DynamicSet`
197 {
198 let mut dynamic_set = DynamicSet::from_iter(["x", "y", "z"]);
199 assert!(dynamic_set.contains(&"x"));
200
201 dynamic_set.remove(&"y");
202
203 let mut my_set: HashSet<&str> = HashSet::default();
204 my_set.apply(&dynamic_set);
205 assert_eq!(my_set, HashSet::from_iter(["x", "z"]));
206 }
207
208 // 5. `DynamicMap`
209 {
210 let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);
211
212 let mut my_map: HashMap<&str, u32> = HashMap::default();
213 my_map.apply(&dynamic_map);
214 assert_eq!(my_map.get("x"), Some(&1));
215 assert_eq!(my_map.get("y"), Some(&2));
216 assert_eq!(my_map.get("z"), Some(&3));
217 }
218
219 // 6. `DynamicStruct`
220 {
221 #[derive(Reflect, Default, Debug, PartialEq)]
222 struct MyStruct {
223 x: u32,
224 y: u32,
225 z: u32,
226 }
227
228 let mut dynamic_struct = DynamicStruct::default();
229 dynamic_struct.insert("x", 1u32);
230 dynamic_struct.insert("y", 2u32);
231 dynamic_struct.insert("z", 3u32);
232
233 let mut my_struct = MyStruct::default();
234 my_struct.apply(&dynamic_struct);
235 assert_eq!(my_struct, MyStruct { x: 1, y: 2, z: 3 });
236 }
237
238 // 7. `DynamicTupleStruct`
239 {
240 #[derive(Reflect, Default, Debug, PartialEq)]
241 struct MyTupleStruct(u32, u32, u32);
242
243 let mut dynamic_tuple_struct = DynamicTupleStruct::default();
244 dynamic_tuple_struct.insert(1u32);
245 dynamic_tuple_struct.insert(2u32);
246 dynamic_tuple_struct.insert(3u32);
247
248 let mut my_tuple_struct = MyTupleStruct::default();
249 my_tuple_struct.apply(&dynamic_tuple_struct);
250 assert_eq!(my_tuple_struct, MyTupleStruct(1, 2, 3));
251 }
252
253 // 8. `DynamicEnum`
254 {
255 #[derive(Reflect, Default, Debug, PartialEq)]
256 enum MyEnum {
257 #[default]
258 Empty,
259 Xyz(u32, u32, u32),
260 }
261
262 let mut values = DynamicTuple::default();
263 values.insert(1u32);
264 values.insert(2u32);
265 values.insert(3u32);
266
267 let dynamic_variant = DynamicVariant::Tuple(values);
268 let dynamic_enum = DynamicEnum::new("Xyz", dynamic_variant);
269
270 let mut my_enum = MyEnum::default();
271 my_enum.apply(&dynamic_enum);
272 assert_eq!(my_enum, MyEnum::Xyz(1, 2, 3));
273 }
274}
Sourcefn reflect_kind(&self) -> ReflectKind
fn reflect_kind(&self) -> ReflectKind
Returns a zero-sized enumeration of “kinds” of type.
See ReflectKind
.
Sourcefn clone_value(&self) -> Box<dyn PartialReflect>
👎Deprecated since 0.16.0: to clone reflected values, prefer using reflect_clone
. To convert reflected values to dynamic ones, use to_dynamic
.
fn clone_value(&self) -> Box<dyn PartialReflect>
reflect_clone
. To convert reflected values to dynamic ones, use to_dynamic
.Clones Self
into its dynamic representation.
For value types or types marked with #[reflect_value]
,
this will simply return a clone of Self
.
Otherwise the associated dynamic type will be returned.
For example, a List
type will invoke List::clone_dynamic
, returning DynamicList
.
A Struct
type will invoke Struct::clone_dynamic
, returning DynamicStruct
.
And so on.
If the dynamic behavior is not desired, a concrete clone can be obtained using PartialReflect::reflect_clone
.
§Example
let value = (1, true, 3.14);
let cloned = value.clone_value();
assert!(cloned.is_dynamic())
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?
12fn main() {
13 #[derive(Reflect, Default, PartialEq, Debug)]
14 #[reflect(Identifiable, Default)]
15 struct Player {
16 id: u32,
17 }
18
19 #[reflect_trait]
20 trait Identifiable {
21 fn id(&self) -> u32;
22 }
23
24 impl Identifiable for Player {
25 fn id(&self) -> u32 {
26 self.id
27 }
28 }
29
30 // Normally, when instantiating a type, you get back exactly that type.
31 // This is because the type is known at compile time.
32 // We call this the "concrete" or "canonical" type.
33 let player: Player = Player { id: 123 };
34
35 // When working with reflected types, however, we often "erase" this type information
36 // using the `Reflect` trait object.
37 // This trait object also gives us access to all the methods in the `PartialReflect` trait too.
38 // The underlying type is still the same (in this case, `Player`),
39 // but now we've hidden that information from the compiler.
40 let reflected: Box<dyn Reflect> = Box::new(player);
41
42 // Because it's the same type under the hood, we can still downcast it back to the original type.
43 assert!(reflected.downcast_ref::<Player>().is_some());
44
45 // We can attempt to clone our value using `PartialReflect::reflect_clone`.
46 // This will recursively call `PartialReflect::reflect_clone` on all fields of the type.
47 // Or, if we had registered `ReflectClone` using `#[reflect(Clone)]`, it would simply call `Clone::clone` directly.
48 let cloned: Box<dyn Reflect> = reflected.reflect_clone().unwrap();
49 assert_eq!(cloned.downcast_ref::<Player>(), Some(&Player { id: 123 }));
50
51 // Another way we can "clone" our data is by converting it to a dynamic type.
52 // Notice here we bind it as a `dyn PartialReflect` instead of `dyn Reflect`.
53 // This is because it returns a dynamic type that simply represents the original type.
54 // In this case, because `Player` is a struct, it will return a `DynamicStruct`.
55 let dynamic: Box<dyn PartialReflect> = reflected.to_dynamic();
56 assert!(dynamic.is_dynamic());
57
58 // And if we try to convert it back to a `dyn Reflect` trait object, we'll get `None`.
59 // Dynamic types cannot be directly cast to `dyn Reflect` trait objects.
60 assert!(dynamic.try_as_reflect().is_none());
61
62 // Generally dynamic types are used to represent (or "proxy") the original type,
63 // so that we can continue to access its fields and overall structure.
64 let dynamic_ref = dynamic.reflect_ref().as_struct().unwrap();
65 let id = dynamic_ref.field("id").unwrap().try_downcast_ref::<u32>();
66 assert_eq!(id, Some(&123));
67
68 // It also enables us to create a representation of a type without having compile-time
69 // access to the actual type. This is how the reflection deserializers work.
70 // They generally can't know how to construct a type ahead of time,
71 // so they instead build and return these dynamic representations.
72 let input = "(id: 123)";
73 let mut registry = TypeRegistry::default();
74 registry.register::<Player>();
75 let registration = registry.get(std::any::TypeId::of::<Player>()).unwrap();
76 let deserialized = TypedReflectDeserializer::new(registration, ®istry)
77 .deserialize(&mut ron::Deserializer::from_str(input).unwrap())
78 .unwrap();
79
80 // Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`.
81 assert!(deserialized.represents::<Player>());
82
83 // And while this does allow us to access the fields and structure of the type,
84 // there may be instances where we need the actual type.
85 // For example, if we want to convert our `dyn Reflect` into a `dyn Identifiable`,
86 // we can't use the `DynamicStruct` proxy.
87 let reflect_identifiable = registration
88 .data::<ReflectIdentifiable>()
89 .expect("`ReflectIdentifiable` should be registered");
90
91 // Trying to access the registry with our `deserialized` will give a compile error
92 // since it doesn't implement `Reflect`, only `PartialReflect`.
93 // Similarly, trying to force the operation will fail.
94 // This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`.
95 assert!(deserialized
96 .try_as_reflect()
97 .and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj))
98 .is_none());
99
100 // So how can we go from a dynamic type to a concrete type?
101 // There are two ways:
102
103 // 1. Using `PartialReflect::apply`.
104 {
105 // If you know the type at compile time, you can construct a new value and apply the dynamic
106 // value to it.
107 let mut value = Player::default();
108 value.apply(deserialized.as_ref());
109 assert_eq!(value.id, 123);
110
111 // If you don't know the type at compile time, you need a dynamic way of constructing
112 // an instance of the type. One such way is to use the `ReflectDefault` type data.
113 let reflect_default = registration
114 .data::<ReflectDefault>()
115 .expect("`ReflectDefault` should be registered");
116
117 let mut value: Box<dyn Reflect> = reflect_default.default();
118 value.apply(deserialized.as_ref());
119
120 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
121 assert_eq!(identifiable.id(), 123);
122 }
123
124 // 2. Using `FromReflect`
125 {
126 // If you know the type at compile time, you can use the `FromReflect` trait to convert the
127 // dynamic value into the concrete type directly.
128 let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap();
129 assert_eq!(value.id, 123);
130
131 // If you don't know the type at compile time, you can use the `ReflectFromReflect` type data
132 // to perform the conversion dynamically.
133 let reflect_from_reflect = registration
134 .data::<ReflectFromReflect>()
135 .expect("`ReflectFromReflect` should be registered");
136
137 let value: Box<dyn Reflect> = reflect_from_reflect
138 .from_reflect(deserialized.as_ref())
139 .unwrap();
140 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
141 assert_eq!(identifiable.id(), 123);
142 }
143
144 // Lastly, while dynamic types are commonly generated via reflection methods like
145 // `PartialReflect::to_dynamic` or via the reflection deserializers,
146 // you can also construct them manually.
147 let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
148
149 // This is useful when you just need to apply some subset of changes to a type.
150 let mut my_list: Vec<u32> = Vec::new();
151 my_list.apply(&my_dynamic_list);
152 assert_eq!(my_list, vec![1, 2, 3]);
153
154 // And if you want it to actually proxy a type, you can configure it to do that as well:
155 assert!(!my_dynamic_list
156 .as_partial_reflect()
157 .represents::<Vec<u32>>());
158 my_dynamic_list.set_represented_type(Some(<Vec<u32>>::type_info()));
159 assert!(my_dynamic_list
160 .as_partial_reflect()
161 .represents::<Vec<u32>>());
162
163 // ============================= REFERENCE ============================= //
164 // For reference, here are all the available dynamic types:
165
166 // 1. `DynamicTuple`
167 {
168 let mut dynamic_tuple = DynamicTuple::default();
169 dynamic_tuple.insert(1u32);
170 dynamic_tuple.insert(2u32);
171 dynamic_tuple.insert(3u32);
172
173 let mut my_tuple: (u32, u32, u32) = (0, 0, 0);
174 my_tuple.apply(&dynamic_tuple);
175 assert_eq!(my_tuple, (1, 2, 3));
176 }
177
178 // 2. `DynamicArray`
179 {
180 let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);
181
182 let mut my_array = [0u32; 3];
183 my_array.apply(&dynamic_array);
184 assert_eq!(my_array, [1, 2, 3]);
185 }
186
187 // 3. `DynamicList`
188 {
189 let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
190
191 let mut my_list: Vec<u32> = Vec::new();
192 my_list.apply(&dynamic_list);
193 assert_eq!(my_list, vec![1, 2, 3]);
194 }
195
196 // 4. `DynamicSet`
197 {
198 let mut dynamic_set = DynamicSet::from_iter(["x", "y", "z"]);
199 assert!(dynamic_set.contains(&"x"));
200
201 dynamic_set.remove(&"y");
202
203 let mut my_set: HashSet<&str> = HashSet::default();
204 my_set.apply(&dynamic_set);
205 assert_eq!(my_set, HashSet::from_iter(["x", "z"]));
206 }
207
208 // 5. `DynamicMap`
209 {
210 let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);
211
212 let mut my_map: HashMap<&str, u32> = HashMap::default();
213 my_map.apply(&dynamic_map);
214 assert_eq!(my_map.get("x"), Some(&1));
215 assert_eq!(my_map.get("y"), Some(&2));
216 assert_eq!(my_map.get("z"), Some(&3));
217 }
218
219 // 6. `DynamicStruct`
220 {
221 #[derive(Reflect, Default, Debug, PartialEq)]
222 struct MyStruct {
223 x: u32,
224 y: u32,
225 z: u32,
226 }
227
228 let mut dynamic_struct = DynamicStruct::default();
229 dynamic_struct.insert("x", 1u32);
230 dynamic_struct.insert("y", 2u32);
231 dynamic_struct.insert("z", 3u32);
232
233 let mut my_struct = MyStruct::default();
234 my_struct.apply(&dynamic_struct);
235 assert_eq!(my_struct, MyStruct { x: 1, y: 2, z: 3 });
236 }
237
238 // 7. `DynamicTupleStruct`
239 {
240 #[derive(Reflect, Default, Debug, PartialEq)]
241 struct MyTupleStruct(u32, u32, u32);
242
243 let mut dynamic_tuple_struct = DynamicTupleStruct::default();
244 dynamic_tuple_struct.insert(1u32);
245 dynamic_tuple_struct.insert(2u32);
246 dynamic_tuple_struct.insert(3u32);
247
248 let mut my_tuple_struct = MyTupleStruct::default();
249 my_tuple_struct.apply(&dynamic_tuple_struct);
250 assert_eq!(my_tuple_struct, MyTupleStruct(1, 2, 3));
251 }
252
253 // 8. `DynamicEnum`
254 {
255 #[derive(Reflect, Default, Debug, PartialEq)]
256 enum MyEnum {
257 #[default]
258 Empty,
259 Xyz(u32, u32, u32),
260 }
261
262 let mut values = DynamicTuple::default();
263 values.insert(1u32);
264 values.insert(2u32);
265 values.insert(3u32);
266
267 let dynamic_variant = DynamicVariant::Tuple(values);
268 let dynamic_enum = DynamicEnum::new("Xyz", dynamic_variant);
269
270 let mut my_enum = MyEnum::default();
271 my_enum.apply(&dynamic_enum);
272 assert_eq!(my_enum, MyEnum::Xyz(1, 2, 3));
273 }
274}
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?
12fn main() {
13 #[derive(Reflect, Default, PartialEq, Debug)]
14 #[reflect(Identifiable, Default)]
15 struct Player {
16 id: u32,
17 }
18
19 #[reflect_trait]
20 trait Identifiable {
21 fn id(&self) -> u32;
22 }
23
24 impl Identifiable for Player {
25 fn id(&self) -> u32 {
26 self.id
27 }
28 }
29
30 // Normally, when instantiating a type, you get back exactly that type.
31 // This is because the type is known at compile time.
32 // We call this the "concrete" or "canonical" type.
33 let player: Player = Player { id: 123 };
34
35 // When working with reflected types, however, we often "erase" this type information
36 // using the `Reflect` trait object.
37 // This trait object also gives us access to all the methods in the `PartialReflect` trait too.
38 // The underlying type is still the same (in this case, `Player`),
39 // but now we've hidden that information from the compiler.
40 let reflected: Box<dyn Reflect> = Box::new(player);
41
42 // Because it's the same type under the hood, we can still downcast it back to the original type.
43 assert!(reflected.downcast_ref::<Player>().is_some());
44
45 // We can attempt to clone our value using `PartialReflect::reflect_clone`.
46 // This will recursively call `PartialReflect::reflect_clone` on all fields of the type.
47 // Or, if we had registered `ReflectClone` using `#[reflect(Clone)]`, it would simply call `Clone::clone` directly.
48 let cloned: Box<dyn Reflect> = reflected.reflect_clone().unwrap();
49 assert_eq!(cloned.downcast_ref::<Player>(), Some(&Player { id: 123 }));
50
51 // Another way we can "clone" our data is by converting it to a dynamic type.
52 // Notice here we bind it as a `dyn PartialReflect` instead of `dyn Reflect`.
53 // This is because it returns a dynamic type that simply represents the original type.
54 // In this case, because `Player` is a struct, it will return a `DynamicStruct`.
55 let dynamic: Box<dyn PartialReflect> = reflected.to_dynamic();
56 assert!(dynamic.is_dynamic());
57
58 // And if we try to convert it back to a `dyn Reflect` trait object, we'll get `None`.
59 // Dynamic types cannot be directly cast to `dyn Reflect` trait objects.
60 assert!(dynamic.try_as_reflect().is_none());
61
62 // Generally dynamic types are used to represent (or "proxy") the original type,
63 // so that we can continue to access its fields and overall structure.
64 let dynamic_ref = dynamic.reflect_ref().as_struct().unwrap();
65 let id = dynamic_ref.field("id").unwrap().try_downcast_ref::<u32>();
66 assert_eq!(id, Some(&123));
67
68 // It also enables us to create a representation of a type without having compile-time
69 // access to the actual type. This is how the reflection deserializers work.
70 // They generally can't know how to construct a type ahead of time,
71 // so they instead build and return these dynamic representations.
72 let input = "(id: 123)";
73 let mut registry = TypeRegistry::default();
74 registry.register::<Player>();
75 let registration = registry.get(std::any::TypeId::of::<Player>()).unwrap();
76 let deserialized = TypedReflectDeserializer::new(registration, ®istry)
77 .deserialize(&mut ron::Deserializer::from_str(input).unwrap())
78 .unwrap();
79
80 // Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`.
81 assert!(deserialized.represents::<Player>());
82
83 // And while this does allow us to access the fields and structure of the type,
84 // there may be instances where we need the actual type.
85 // For example, if we want to convert our `dyn Reflect` into a `dyn Identifiable`,
86 // we can't use the `DynamicStruct` proxy.
87 let reflect_identifiable = registration
88 .data::<ReflectIdentifiable>()
89 .expect("`ReflectIdentifiable` should be registered");
90
91 // Trying to access the registry with our `deserialized` will give a compile error
92 // since it doesn't implement `Reflect`, only `PartialReflect`.
93 // Similarly, trying to force the operation will fail.
94 // This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`.
95 assert!(deserialized
96 .try_as_reflect()
97 .and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj))
98 .is_none());
99
100 // So how can we go from a dynamic type to a concrete type?
101 // There are two ways:
102
103 // 1. Using `PartialReflect::apply`.
104 {
105 // If you know the type at compile time, you can construct a new value and apply the dynamic
106 // value to it.
107 let mut value = Player::default();
108 value.apply(deserialized.as_ref());
109 assert_eq!(value.id, 123);
110
111 // If you don't know the type at compile time, you need a dynamic way of constructing
112 // an instance of the type. One such way is to use the `ReflectDefault` type data.
113 let reflect_default = registration
114 .data::<ReflectDefault>()
115 .expect("`ReflectDefault` should be registered");
116
117 let mut value: Box<dyn Reflect> = reflect_default.default();
118 value.apply(deserialized.as_ref());
119
120 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
121 assert_eq!(identifiable.id(), 123);
122 }
123
124 // 2. Using `FromReflect`
125 {
126 // If you know the type at compile time, you can use the `FromReflect` trait to convert the
127 // dynamic value into the concrete type directly.
128 let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap();
129 assert_eq!(value.id, 123);
130
131 // If you don't know the type at compile time, you can use the `ReflectFromReflect` type data
132 // to perform the conversion dynamically.
133 let reflect_from_reflect = registration
134 .data::<ReflectFromReflect>()
135 .expect("`ReflectFromReflect` should be registered");
136
137 let value: Box<dyn Reflect> = reflect_from_reflect
138 .from_reflect(deserialized.as_ref())
139 .unwrap();
140 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
141 assert_eq!(identifiable.id(), 123);
142 }
143
144 // Lastly, while dynamic types are commonly generated via reflection methods like
145 // `PartialReflect::to_dynamic` or via the reflection deserializers,
146 // you can also construct them manually.
147 let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
148
149 // This is useful when you just need to apply some subset of changes to a type.
150 let mut my_list: Vec<u32> = Vec::new();
151 my_list.apply(&my_dynamic_list);
152 assert_eq!(my_list, vec![1, 2, 3]);
153
154 // And if you want it to actually proxy a type, you can configure it to do that as well:
155 assert!(!my_dynamic_list
156 .as_partial_reflect()
157 .represents::<Vec<u32>>());
158 my_dynamic_list.set_represented_type(Some(<Vec<u32>>::type_info()));
159 assert!(my_dynamic_list
160 .as_partial_reflect()
161 .represents::<Vec<u32>>());
162
163 // ============================= REFERENCE ============================= //
164 // For reference, here are all the available dynamic types:
165
166 // 1. `DynamicTuple`
167 {
168 let mut dynamic_tuple = DynamicTuple::default();
169 dynamic_tuple.insert(1u32);
170 dynamic_tuple.insert(2u32);
171 dynamic_tuple.insert(3u32);
172
173 let mut my_tuple: (u32, u32, u32) = (0, 0, 0);
174 my_tuple.apply(&dynamic_tuple);
175 assert_eq!(my_tuple, (1, 2, 3));
176 }
177
178 // 2. `DynamicArray`
179 {
180 let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);
181
182 let mut my_array = [0u32; 3];
183 my_array.apply(&dynamic_array);
184 assert_eq!(my_array, [1, 2, 3]);
185 }
186
187 // 3. `DynamicList`
188 {
189 let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
190
191 let mut my_list: Vec<u32> = Vec::new();
192 my_list.apply(&dynamic_list);
193 assert_eq!(my_list, vec![1, 2, 3]);
194 }
195
196 // 4. `DynamicSet`
197 {
198 let mut dynamic_set = DynamicSet::from_iter(["x", "y", "z"]);
199 assert!(dynamic_set.contains(&"x"));
200
201 dynamic_set.remove(&"y");
202
203 let mut my_set: HashSet<&str> = HashSet::default();
204 my_set.apply(&dynamic_set);
205 assert_eq!(my_set, HashSet::from_iter(["x", "z"]));
206 }
207
208 // 5. `DynamicMap`
209 {
210 let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);
211
212 let mut my_map: HashMap<&str, u32> = HashMap::default();
213 my_map.apply(&dynamic_map);
214 assert_eq!(my_map.get("x"), Some(&1));
215 assert_eq!(my_map.get("y"), Some(&2));
216 assert_eq!(my_map.get("z"), Some(&3));
217 }
218
219 // 6. `DynamicStruct`
220 {
221 #[derive(Reflect, Default, Debug, PartialEq)]
222 struct MyStruct {
223 x: u32,
224 y: u32,
225 z: u32,
226 }
227
228 let mut dynamic_struct = DynamicStruct::default();
229 dynamic_struct.insert("x", 1u32);
230 dynamic_struct.insert("y", 2u32);
231 dynamic_struct.insert("z", 3u32);
232
233 let mut my_struct = MyStruct::default();
234 my_struct.apply(&dynamic_struct);
235 assert_eq!(my_struct, MyStruct { x: 1, y: 2, z: 3 });
236 }
237
238 // 7. `DynamicTupleStruct`
239 {
240 #[derive(Reflect, Default, Debug, PartialEq)]
241 struct MyTupleStruct(u32, u32, u32);
242
243 let mut dynamic_tuple_struct = DynamicTupleStruct::default();
244 dynamic_tuple_struct.insert(1u32);
245 dynamic_tuple_struct.insert(2u32);
246 dynamic_tuple_struct.insert(3u32);
247
248 let mut my_tuple_struct = MyTupleStruct::default();
249 my_tuple_struct.apply(&dynamic_tuple_struct);
250 assert_eq!(my_tuple_struct, MyTupleStruct(1, 2, 3));
251 }
252
253 // 8. `DynamicEnum`
254 {
255 #[derive(Reflect, Default, Debug, PartialEq)]
256 enum MyEnum {
257 #[default]
258 Empty,
259 Xyz(u32, u32, u32),
260 }
261
262 let mut values = DynamicTuple::default();
263 values.insert(1u32);
264 values.insert(2u32);
265 values.insert(3u32);
266
267 let dynamic_variant = DynamicVariant::Tuple(values);
268 let dynamic_enum = DynamicEnum::new("Xyz", dynamic_variant);
269
270 let mut my_enum = MyEnum::default();
271 my_enum.apply(&dynamic_enum);
272 assert_eq!(my_enum, MyEnum::Xyz(1, 2, 3));
273 }
274}
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?
56fn setup(type_registry: Res<AppTypeRegistry>) {
57 let mut value = Foo {
58 a: 1,
59 _ignored: NonReflectedValue { _a: 10 },
60 nested: Bar { b: 8 },
61 };
62
63 // You can set field values like this. The type must match exactly or this will fail.
64 *value.get_field_mut("a").unwrap() = 2usize;
65 assert_eq!(value.a, 2);
66 assert_eq!(*value.get_field::<usize>("a").unwrap(), 2);
67
68 // You can also get the `&dyn PartialReflect` value of a field like this
69 let field = value.field("a").unwrap();
70
71 // But values introspected via `PartialReflect` will not return `dyn Reflect` trait objects
72 // (even if the containing type does implement `Reflect`), so we need to convert them:
73 let fully_reflected_field = field.try_as_reflect().unwrap();
74
75 // Now, you can downcast your `Reflect` value like this:
76 assert_eq!(*fully_reflected_field.downcast_ref::<usize>().unwrap(), 2);
77
78 // For this specific case, we also support the shortcut `try_downcast_ref`:
79 assert_eq!(*field.try_downcast_ref::<usize>().unwrap(), 2);
80
81 // `DynamicStruct` also implements the `Struct` and `Reflect` traits.
82 let mut patch = DynamicStruct::default();
83 patch.insert("a", 4usize);
84
85 // You can "apply" Reflect implementations on top of other Reflect implementations.
86 // This will only set fields with the same name, and it will fail if the types don't match.
87 // You can use this to "patch" your types with new values.
88 value.apply(&patch);
89 assert_eq!(value.a, 4);
90
91 let type_registry = type_registry.read();
92 // By default, all derived `Reflect` types can be Serialized using serde. No need to derive
93 // Serialize!
94 let serializer = ReflectSerializer::new(&value, &type_registry);
95 let ron_string =
96 ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
97 info!("{}\n", ron_string);
98
99 // Dynamic properties can be deserialized
100 let reflect_deserializer = ReflectDeserializer::new(&type_registry);
101 let mut deserializer = ron::de::Deserializer::from_str(&ron_string).unwrap();
102 let reflect_value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
103
104 // Deserializing returns a `Box<dyn PartialReflect>` value.
105 // Generally, deserializing a value will return the "dynamic" variant of a type.
106 // For example, deserializing a struct will return the DynamicStruct type.
107 // "Opaque types" will be deserialized as themselves.
108 assert_eq!(
109 reflect_value.reflect_type_path(),
110 DynamicStruct::type_path(),
111 );
112
113 // Reflect has its own `partial_eq` implementation, named `reflect_partial_eq`. This behaves
114 // like normal `partial_eq`, but it treats "dynamic" and "non-dynamic" types the same. The
115 // `Foo` struct and deserialized `DynamicStruct` are considered equal for this reason:
116 assert!(reflect_value.reflect_partial_eq(&value).unwrap());
117
118 // By "patching" `Foo` with the deserialized DynamicStruct, we can "Deserialize" Foo.
119 // This means we can serialize and deserialize with a single `Reflect` derive!
120 value.apply(&*reflect_value);
121}
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?
12fn main() {
13 #[derive(Reflect, Default, PartialEq, Debug)]
14 #[reflect(Identifiable, Default)]
15 struct Player {
16 id: u32,
17 }
18
19 #[reflect_trait]
20 trait Identifiable {
21 fn id(&self) -> u32;
22 }
23
24 impl Identifiable for Player {
25 fn id(&self) -> u32 {
26 self.id
27 }
28 }
29
30 // Normally, when instantiating a type, you get back exactly that type.
31 // This is because the type is known at compile time.
32 // We call this the "concrete" or "canonical" type.
33 let player: Player = Player { id: 123 };
34
35 // When working with reflected types, however, we often "erase" this type information
36 // using the `Reflect` trait object.
37 // This trait object also gives us access to all the methods in the `PartialReflect` trait too.
38 // The underlying type is still the same (in this case, `Player`),
39 // but now we've hidden that information from the compiler.
40 let reflected: Box<dyn Reflect> = Box::new(player);
41
42 // Because it's the same type under the hood, we can still downcast it back to the original type.
43 assert!(reflected.downcast_ref::<Player>().is_some());
44
45 // We can attempt to clone our value using `PartialReflect::reflect_clone`.
46 // This will recursively call `PartialReflect::reflect_clone` on all fields of the type.
47 // Or, if we had registered `ReflectClone` using `#[reflect(Clone)]`, it would simply call `Clone::clone` directly.
48 let cloned: Box<dyn Reflect> = reflected.reflect_clone().unwrap();
49 assert_eq!(cloned.downcast_ref::<Player>(), Some(&Player { id: 123 }));
50
51 // Another way we can "clone" our data is by converting it to a dynamic type.
52 // Notice here we bind it as a `dyn PartialReflect` instead of `dyn Reflect`.
53 // This is because it returns a dynamic type that simply represents the original type.
54 // In this case, because `Player` is a struct, it will return a `DynamicStruct`.
55 let dynamic: Box<dyn PartialReflect> = reflected.to_dynamic();
56 assert!(dynamic.is_dynamic());
57
58 // And if we try to convert it back to a `dyn Reflect` trait object, we'll get `None`.
59 // Dynamic types cannot be directly cast to `dyn Reflect` trait objects.
60 assert!(dynamic.try_as_reflect().is_none());
61
62 // Generally dynamic types are used to represent (or "proxy") the original type,
63 // so that we can continue to access its fields and overall structure.
64 let dynamic_ref = dynamic.reflect_ref().as_struct().unwrap();
65 let id = dynamic_ref.field("id").unwrap().try_downcast_ref::<u32>();
66 assert_eq!(id, Some(&123));
67
68 // It also enables us to create a representation of a type without having compile-time
69 // access to the actual type. This is how the reflection deserializers work.
70 // They generally can't know how to construct a type ahead of time,
71 // so they instead build and return these dynamic representations.
72 let input = "(id: 123)";
73 let mut registry = TypeRegistry::default();
74 registry.register::<Player>();
75 let registration = registry.get(std::any::TypeId::of::<Player>()).unwrap();
76 let deserialized = TypedReflectDeserializer::new(registration, ®istry)
77 .deserialize(&mut ron::Deserializer::from_str(input).unwrap())
78 .unwrap();
79
80 // Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`.
81 assert!(deserialized.represents::<Player>());
82
83 // And while this does allow us to access the fields and structure of the type,
84 // there may be instances where we need the actual type.
85 // For example, if we want to convert our `dyn Reflect` into a `dyn Identifiable`,
86 // we can't use the `DynamicStruct` proxy.
87 let reflect_identifiable = registration
88 .data::<ReflectIdentifiable>()
89 .expect("`ReflectIdentifiable` should be registered");
90
91 // Trying to access the registry with our `deserialized` will give a compile error
92 // since it doesn't implement `Reflect`, only `PartialReflect`.
93 // Similarly, trying to force the operation will fail.
94 // This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`.
95 assert!(deserialized
96 .try_as_reflect()
97 .and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj))
98 .is_none());
99
100 // So how can we go from a dynamic type to a concrete type?
101 // There are two ways:
102
103 // 1. Using `PartialReflect::apply`.
104 {
105 // If you know the type at compile time, you can construct a new value and apply the dynamic
106 // value to it.
107 let mut value = Player::default();
108 value.apply(deserialized.as_ref());
109 assert_eq!(value.id, 123);
110
111 // If you don't know the type at compile time, you need a dynamic way of constructing
112 // an instance of the type. One such way is to use the `ReflectDefault` type data.
113 let reflect_default = registration
114 .data::<ReflectDefault>()
115 .expect("`ReflectDefault` should be registered");
116
117 let mut value: Box<dyn Reflect> = reflect_default.default();
118 value.apply(deserialized.as_ref());
119
120 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
121 assert_eq!(identifiable.id(), 123);
122 }
123
124 // 2. Using `FromReflect`
125 {
126 // If you know the type at compile time, you can use the `FromReflect` trait to convert the
127 // dynamic value into the concrete type directly.
128 let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap();
129 assert_eq!(value.id, 123);
130
131 // If you don't know the type at compile time, you can use the `ReflectFromReflect` type data
132 // to perform the conversion dynamically.
133 let reflect_from_reflect = registration
134 .data::<ReflectFromReflect>()
135 .expect("`ReflectFromReflect` should be registered");
136
137 let value: Box<dyn Reflect> = reflect_from_reflect
138 .from_reflect(deserialized.as_ref())
139 .unwrap();
140 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
141 assert_eq!(identifiable.id(), 123);
142 }
143
144 // Lastly, while dynamic types are commonly generated via reflection methods like
145 // `PartialReflect::to_dynamic` or via the reflection deserializers,
146 // you can also construct them manually.
147 let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
148
149 // This is useful when you just need to apply some subset of changes to a type.
150 let mut my_list: Vec<u32> = Vec::new();
151 my_list.apply(&my_dynamic_list);
152 assert_eq!(my_list, vec![1, 2, 3]);
153
154 // And if you want it to actually proxy a type, you can configure it to do that as well:
155 assert!(!my_dynamic_list
156 .as_partial_reflect()
157 .represents::<Vec<u32>>());
158 my_dynamic_list.set_represented_type(Some(<Vec<u32>>::type_info()));
159 assert!(my_dynamic_list
160 .as_partial_reflect()
161 .represents::<Vec<u32>>());
162
163 // ============================= REFERENCE ============================= //
164 // For reference, here are all the available dynamic types:
165
166 // 1. `DynamicTuple`
167 {
168 let mut dynamic_tuple = DynamicTuple::default();
169 dynamic_tuple.insert(1u32);
170 dynamic_tuple.insert(2u32);
171 dynamic_tuple.insert(3u32);
172
173 let mut my_tuple: (u32, u32, u32) = (0, 0, 0);
174 my_tuple.apply(&dynamic_tuple);
175 assert_eq!(my_tuple, (1, 2, 3));
176 }
177
178 // 2. `DynamicArray`
179 {
180 let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);
181
182 let mut my_array = [0u32; 3];
183 my_array.apply(&dynamic_array);
184 assert_eq!(my_array, [1, 2, 3]);
185 }
186
187 // 3. `DynamicList`
188 {
189 let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
190
191 let mut my_list: Vec<u32> = Vec::new();
192 my_list.apply(&dynamic_list);
193 assert_eq!(my_list, vec![1, 2, 3]);
194 }
195
196 // 4. `DynamicSet`
197 {
198 let mut dynamic_set = DynamicSet::from_iter(["x", "y", "z"]);
199 assert!(dynamic_set.contains(&"x"));
200
201 dynamic_set.remove(&"y");
202
203 let mut my_set: HashSet<&str> = HashSet::default();
204 my_set.apply(&dynamic_set);
205 assert_eq!(my_set, HashSet::from_iter(["x", "z"]));
206 }
207
208 // 5. `DynamicMap`
209 {
210 let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);
211
212 let mut my_map: HashMap<&str, u32> = HashMap::default();
213 my_map.apply(&dynamic_map);
214 assert_eq!(my_map.get("x"), Some(&1));
215 assert_eq!(my_map.get("y"), Some(&2));
216 assert_eq!(my_map.get("z"), Some(&3));
217 }
218
219 // 6. `DynamicStruct`
220 {
221 #[derive(Reflect, Default, Debug, PartialEq)]
222 struct MyStruct {
223 x: u32,
224 y: u32,
225 z: u32,
226 }
227
228 let mut dynamic_struct = DynamicStruct::default();
229 dynamic_struct.insert("x", 1u32);
230 dynamic_struct.insert("y", 2u32);
231 dynamic_struct.insert("z", 3u32);
232
233 let mut my_struct = MyStruct::default();
234 my_struct.apply(&dynamic_struct);
235 assert_eq!(my_struct, MyStruct { x: 1, y: 2, z: 3 });
236 }
237
238 // 7. `DynamicTupleStruct`
239 {
240 #[derive(Reflect, Default, Debug, PartialEq)]
241 struct MyTupleStruct(u32, u32, u32);
242
243 let mut dynamic_tuple_struct = DynamicTupleStruct::default();
244 dynamic_tuple_struct.insert(1u32);
245 dynamic_tuple_struct.insert(2u32);
246 dynamic_tuple_struct.insert(3u32);
247
248 let mut my_tuple_struct = MyTupleStruct::default();
249 my_tuple_struct.apply(&dynamic_tuple_struct);
250 assert_eq!(my_tuple_struct, MyTupleStruct(1, 2, 3));
251 }
252
253 // 8. `DynamicEnum`
254 {
255 #[derive(Reflect, Default, Debug, PartialEq)]
256 enum MyEnum {
257 #[default]
258 Empty,
259 Xyz(u32, u32, u32),
260 }
261
262 let mut values = DynamicTuple::default();
263 values.insert(1u32);
264 values.insert(2u32);
265 values.insert(3u32);
266
267 let dynamic_variant = DynamicVariant::Tuple(values);
268 let dynamic_enum = DynamicEnum::new("Xyz", dynamic_variant);
269
270 let mut my_enum = MyEnum::default();
271 my_enum.apply(&dynamic_enum);
272 assert_eq!(my_enum, MyEnum::Xyz(1, 2, 3));
273 }
274}
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?
12fn main() {
13 #[derive(Reflect, Default, PartialEq, Debug)]
14 #[reflect(Identifiable, Default)]
15 struct Player {
16 id: u32,
17 }
18
19 #[reflect_trait]
20 trait Identifiable {
21 fn id(&self) -> u32;
22 }
23
24 impl Identifiable for Player {
25 fn id(&self) -> u32 {
26 self.id
27 }
28 }
29
30 // Normally, when instantiating a type, you get back exactly that type.
31 // This is because the type is known at compile time.
32 // We call this the "concrete" or "canonical" type.
33 let player: Player = Player { id: 123 };
34
35 // When working with reflected types, however, we often "erase" this type information
36 // using the `Reflect` trait object.
37 // This trait object also gives us access to all the methods in the `PartialReflect` trait too.
38 // The underlying type is still the same (in this case, `Player`),
39 // but now we've hidden that information from the compiler.
40 let reflected: Box<dyn Reflect> = Box::new(player);
41
42 // Because it's the same type under the hood, we can still downcast it back to the original type.
43 assert!(reflected.downcast_ref::<Player>().is_some());
44
45 // We can attempt to clone our value using `PartialReflect::reflect_clone`.
46 // This will recursively call `PartialReflect::reflect_clone` on all fields of the type.
47 // Or, if we had registered `ReflectClone` using `#[reflect(Clone)]`, it would simply call `Clone::clone` directly.
48 let cloned: Box<dyn Reflect> = reflected.reflect_clone().unwrap();
49 assert_eq!(cloned.downcast_ref::<Player>(), Some(&Player { id: 123 }));
50
51 // Another way we can "clone" our data is by converting it to a dynamic type.
52 // Notice here we bind it as a `dyn PartialReflect` instead of `dyn Reflect`.
53 // This is because it returns a dynamic type that simply represents the original type.
54 // In this case, because `Player` is a struct, it will return a `DynamicStruct`.
55 let dynamic: Box<dyn PartialReflect> = reflected.to_dynamic();
56 assert!(dynamic.is_dynamic());
57
58 // And if we try to convert it back to a `dyn Reflect` trait object, we'll get `None`.
59 // Dynamic types cannot be directly cast to `dyn Reflect` trait objects.
60 assert!(dynamic.try_as_reflect().is_none());
61
62 // Generally dynamic types are used to represent (or "proxy") the original type,
63 // so that we can continue to access its fields and overall structure.
64 let dynamic_ref = dynamic.reflect_ref().as_struct().unwrap();
65 let id = dynamic_ref.field("id").unwrap().try_downcast_ref::<u32>();
66 assert_eq!(id, Some(&123));
67
68 // It also enables us to create a representation of a type without having compile-time
69 // access to the actual type. This is how the reflection deserializers work.
70 // They generally can't know how to construct a type ahead of time,
71 // so they instead build and return these dynamic representations.
72 let input = "(id: 123)";
73 let mut registry = TypeRegistry::default();
74 registry.register::<Player>();
75 let registration = registry.get(std::any::TypeId::of::<Player>()).unwrap();
76 let deserialized = TypedReflectDeserializer::new(registration, ®istry)
77 .deserialize(&mut ron::Deserializer::from_str(input).unwrap())
78 .unwrap();
79
80 // Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`.
81 assert!(deserialized.represents::<Player>());
82
83 // And while this does allow us to access the fields and structure of the type,
84 // there may be instances where we need the actual type.
85 // For example, if we want to convert our `dyn Reflect` into a `dyn Identifiable`,
86 // we can't use the `DynamicStruct` proxy.
87 let reflect_identifiable = registration
88 .data::<ReflectIdentifiable>()
89 .expect("`ReflectIdentifiable` should be registered");
90
91 // Trying to access the registry with our `deserialized` will give a compile error
92 // since it doesn't implement `Reflect`, only `PartialReflect`.
93 // Similarly, trying to force the operation will fail.
94 // This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`.
95 assert!(deserialized
96 .try_as_reflect()
97 .and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj))
98 .is_none());
99
100 // So how can we go from a dynamic type to a concrete type?
101 // There are two ways:
102
103 // 1. Using `PartialReflect::apply`.
104 {
105 // If you know the type at compile time, you can construct a new value and apply the dynamic
106 // value to it.
107 let mut value = Player::default();
108 value.apply(deserialized.as_ref());
109 assert_eq!(value.id, 123);
110
111 // If you don't know the type at compile time, you need a dynamic way of constructing
112 // an instance of the type. One such way is to use the `ReflectDefault` type data.
113 let reflect_default = registration
114 .data::<ReflectDefault>()
115 .expect("`ReflectDefault` should be registered");
116
117 let mut value: Box<dyn Reflect> = reflect_default.default();
118 value.apply(deserialized.as_ref());
119
120 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
121 assert_eq!(identifiable.id(), 123);
122 }
123
124 // 2. Using `FromReflect`
125 {
126 // If you know the type at compile time, you can use the `FromReflect` trait to convert the
127 // dynamic value into the concrete type directly.
128 let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap();
129 assert_eq!(value.id, 123);
130
131 // If you don't know the type at compile time, you can use the `ReflectFromReflect` type data
132 // to perform the conversion dynamically.
133 let reflect_from_reflect = registration
134 .data::<ReflectFromReflect>()
135 .expect("`ReflectFromReflect` should be registered");
136
137 let value: Box<dyn Reflect> = reflect_from_reflect
138 .from_reflect(deserialized.as_ref())
139 .unwrap();
140 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
141 assert_eq!(identifiable.id(), 123);
142 }
143
144 // Lastly, while dynamic types are commonly generated via reflection methods like
145 // `PartialReflect::to_dynamic` or via the reflection deserializers,
146 // you can also construct them manually.
147 let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
148
149 // This is useful when you just need to apply some subset of changes to a type.
150 let mut my_list: Vec<u32> = Vec::new();
151 my_list.apply(&my_dynamic_list);
152 assert_eq!(my_list, vec![1, 2, 3]);
153
154 // And if you want it to actually proxy a type, you can configure it to do that as well:
155 assert!(!my_dynamic_list
156 .as_partial_reflect()
157 .represents::<Vec<u32>>());
158 my_dynamic_list.set_represented_type(Some(<Vec<u32>>::type_info()));
159 assert!(my_dynamic_list
160 .as_partial_reflect()
161 .represents::<Vec<u32>>());
162
163 // ============================= REFERENCE ============================= //
164 // For reference, here are all the available dynamic types:
165
166 // 1. `DynamicTuple`
167 {
168 let mut dynamic_tuple = DynamicTuple::default();
169 dynamic_tuple.insert(1u32);
170 dynamic_tuple.insert(2u32);
171 dynamic_tuple.insert(3u32);
172
173 let mut my_tuple: (u32, u32, u32) = (0, 0, 0);
174 my_tuple.apply(&dynamic_tuple);
175 assert_eq!(my_tuple, (1, 2, 3));
176 }
177
178 // 2. `DynamicArray`
179 {
180 let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);
181
182 let mut my_array = [0u32; 3];
183 my_array.apply(&dynamic_array);
184 assert_eq!(my_array, [1, 2, 3]);
185 }
186
187 // 3. `DynamicList`
188 {
189 let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
190
191 let mut my_list: Vec<u32> = Vec::new();
192 my_list.apply(&dynamic_list);
193 assert_eq!(my_list, vec![1, 2, 3]);
194 }
195
196 // 4. `DynamicSet`
197 {
198 let mut dynamic_set = DynamicSet::from_iter(["x", "y", "z"]);
199 assert!(dynamic_set.contains(&"x"));
200
201 dynamic_set.remove(&"y");
202
203 let mut my_set: HashSet<&str> = HashSet::default();
204 my_set.apply(&dynamic_set);
205 assert_eq!(my_set, HashSet::from_iter(["x", "z"]));
206 }
207
208 // 5. `DynamicMap`
209 {
210 let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);
211
212 let mut my_map: HashMap<&str, u32> = HashMap::default();
213 my_map.apply(&dynamic_map);
214 assert_eq!(my_map.get("x"), Some(&1));
215 assert_eq!(my_map.get("y"), Some(&2));
216 assert_eq!(my_map.get("z"), Some(&3));
217 }
218
219 // 6. `DynamicStruct`
220 {
221 #[derive(Reflect, Default, Debug, PartialEq)]
222 struct MyStruct {
223 x: u32,
224 y: u32,
225 z: u32,
226 }
227
228 let mut dynamic_struct = DynamicStruct::default();
229 dynamic_struct.insert("x", 1u32);
230 dynamic_struct.insert("y", 2u32);
231 dynamic_struct.insert("z", 3u32);
232
233 let mut my_struct = MyStruct::default();
234 my_struct.apply(&dynamic_struct);
235 assert_eq!(my_struct, MyStruct { x: 1, y: 2, z: 3 });
236 }
237
238 // 7. `DynamicTupleStruct`
239 {
240 #[derive(Reflect, Default, Debug, PartialEq)]
241 struct MyTupleStruct(u32, u32, u32);
242
243 let mut dynamic_tuple_struct = DynamicTupleStruct::default();
244 dynamic_tuple_struct.insert(1u32);
245 dynamic_tuple_struct.insert(2u32);
246 dynamic_tuple_struct.insert(3u32);
247
248 let mut my_tuple_struct = MyTupleStruct::default();
249 my_tuple_struct.apply(&dynamic_tuple_struct);
250 assert_eq!(my_tuple_struct, MyTupleStruct(1, 2, 3));
251 }
252
253 // 8. `DynamicEnum`
254 {
255 #[derive(Reflect, Default, Debug, PartialEq)]
256 enum MyEnum {
257 #[default]
258 Empty,
259 Xyz(u32, u32, u32),
260 }
261
262 let mut values = DynamicTuple::default();
263 values.insert(1u32);
264 values.insert(2u32);
265 values.insert(3u32);
266
267 let dynamic_variant = DynamicVariant::Tuple(values);
268 let dynamic_enum = DynamicEnum::new("Xyz", dynamic_variant);
269
270 let mut my_enum = MyEnum::default();
271 my_enum.apply(&dynamic_enum);
272 assert_eq!(my_enum, MyEnum::Xyz(1, 2, 3));
273 }
274}
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(PartialEq
More examples
56fn setup(type_registry: Res<AppTypeRegistry>) {
57 let mut value = Foo {
58 a: 1,
59 _ignored: NonReflectedValue { _a: 10 },
60 nested: Bar { b: 8 },
61 };
62
63 // You can set field values like this. The type must match exactly or this will fail.
64 *value.get_field_mut("a").unwrap() = 2usize;
65 assert_eq!(value.a, 2);
66 assert_eq!(*value.get_field::<usize>("a").unwrap(), 2);
67
68 // You can also get the `&dyn PartialReflect` value of a field like this
69 let field = value.field("a").unwrap();
70
71 // But values introspected via `PartialReflect` will not return `dyn Reflect` trait objects
72 // (even if the containing type does implement `Reflect`), so we need to convert them:
73 let fully_reflected_field = field.try_as_reflect().unwrap();
74
75 // Now, you can downcast your `Reflect` value like this:
76 assert_eq!(*fully_reflected_field.downcast_ref::<usize>().unwrap(), 2);
77
78 // For this specific case, we also support the shortcut `try_downcast_ref`:
79 assert_eq!(*field.try_downcast_ref::<usize>().unwrap(), 2);
80
81 // `DynamicStruct` also implements the `Struct` and `Reflect` traits.
82 let mut patch = DynamicStruct::default();
83 patch.insert("a", 4usize);
84
85 // You can "apply" Reflect implementations on top of other Reflect implementations.
86 // This will only set fields with the same name, and it will fail if the types don't match.
87 // You can use this to "patch" your types with new values.
88 value.apply(&patch);
89 assert_eq!(value.a, 4);
90
91 let type_registry = type_registry.read();
92 // By default, all derived `Reflect` types can be Serialized using serde. No need to derive
93 // Serialize!
94 let serializer = ReflectSerializer::new(&value, &type_registry);
95 let ron_string =
96 ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
97 info!("{}\n", ron_string);
98
99 // Dynamic properties can be deserialized
100 let reflect_deserializer = ReflectDeserializer::new(&type_registry);
101 let mut deserializer = ron::de::Deserializer::from_str(&ron_string).unwrap();
102 let reflect_value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
103
104 // Deserializing returns a `Box<dyn PartialReflect>` value.
105 // Generally, deserializing a value will return the "dynamic" variant of a type.
106 // For example, deserializing a struct will return the DynamicStruct type.
107 // "Opaque types" will be deserialized as themselves.
108 assert_eq!(
109 reflect_value.reflect_type_path(),
110 DynamicStruct::type_path(),
111 );
112
113 // Reflect has its own `partial_eq` implementation, named `reflect_partial_eq`. This behaves
114 // like normal `partial_eq`, but it treats "dynamic" and "non-dynamic" types the same. The
115 // `Foo` struct and deserialized `DynamicStruct` are considered equal for this reason:
116 assert!(reflect_value.reflect_partial_eq(&value).unwrap());
117
118 // By "patching" `Foo` with the deserialized DynamicStruct, we can "Deserialize" Foo.
119 // This means we can serialize and deserialize with a single `Reflect` derive!
120 value.apply(&*reflect_value);
121}
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}
12fn main() {
13 #[derive(Reflect, Default, PartialEq, Debug)]
14 #[reflect(Identifiable, Default)]
15 struct Player {
16 id: u32,
17 }
18
19 #[reflect_trait]
20 trait Identifiable {
21 fn id(&self) -> u32;
22 }
23
24 impl Identifiable for Player {
25 fn id(&self) -> u32 {
26 self.id
27 }
28 }
29
30 // Normally, when instantiating a type, you get back exactly that type.
31 // This is because the type is known at compile time.
32 // We call this the "concrete" or "canonical" type.
33 let player: Player = Player { id: 123 };
34
35 // When working with reflected types, however, we often "erase" this type information
36 // using the `Reflect` trait object.
37 // This trait object also gives us access to all the methods in the `PartialReflect` trait too.
38 // The underlying type is still the same (in this case, `Player`),
39 // but now we've hidden that information from the compiler.
40 let reflected: Box<dyn Reflect> = Box::new(player);
41
42 // Because it's the same type under the hood, we can still downcast it back to the original type.
43 assert!(reflected.downcast_ref::<Player>().is_some());
44
45 // We can attempt to clone our value using `PartialReflect::reflect_clone`.
46 // This will recursively call `PartialReflect::reflect_clone` on all fields of the type.
47 // Or, if we had registered `ReflectClone` using `#[reflect(Clone)]`, it would simply call `Clone::clone` directly.
48 let cloned: Box<dyn Reflect> = reflected.reflect_clone().unwrap();
49 assert_eq!(cloned.downcast_ref::<Player>(), Some(&Player { id: 123 }));
50
51 // Another way we can "clone" our data is by converting it to a dynamic type.
52 // Notice here we bind it as a `dyn PartialReflect` instead of `dyn Reflect`.
53 // This is because it returns a dynamic type that simply represents the original type.
54 // In this case, because `Player` is a struct, it will return a `DynamicStruct`.
55 let dynamic: Box<dyn PartialReflect> = reflected.to_dynamic();
56 assert!(dynamic.is_dynamic());
57
58 // And if we try to convert it back to a `dyn Reflect` trait object, we'll get `None`.
59 // Dynamic types cannot be directly cast to `dyn Reflect` trait objects.
60 assert!(dynamic.try_as_reflect().is_none());
61
62 // Generally dynamic types are used to represent (or "proxy") the original type,
63 // so that we can continue to access its fields and overall structure.
64 let dynamic_ref = dynamic.reflect_ref().as_struct().unwrap();
65 let id = dynamic_ref.field("id").unwrap().try_downcast_ref::<u32>();
66 assert_eq!(id, Some(&123));
67
68 // It also enables us to create a representation of a type without having compile-time
69 // access to the actual type. This is how the reflection deserializers work.
70 // They generally can't know how to construct a type ahead of time,
71 // so they instead build and return these dynamic representations.
72 let input = "(id: 123)";
73 let mut registry = TypeRegistry::default();
74 registry.register::<Player>();
75 let registration = registry.get(std::any::TypeId::of::<Player>()).unwrap();
76 let deserialized = TypedReflectDeserializer::new(registration, ®istry)
77 .deserialize(&mut ron::Deserializer::from_str(input).unwrap())
78 .unwrap();
79
80 // Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`.
81 assert!(deserialized.represents::<Player>());
82
83 // And while this does allow us to access the fields and structure of the type,
84 // there may be instances where we need the actual type.
85 // For example, if we want to convert our `dyn Reflect` into a `dyn Identifiable`,
86 // we can't use the `DynamicStruct` proxy.
87 let reflect_identifiable = registration
88 .data::<ReflectIdentifiable>()
89 .expect("`ReflectIdentifiable` should be registered");
90
91 // Trying to access the registry with our `deserialized` will give a compile error
92 // since it doesn't implement `Reflect`, only `PartialReflect`.
93 // Similarly, trying to force the operation will fail.
94 // This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`.
95 assert!(deserialized
96 .try_as_reflect()
97 .and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj))
98 .is_none());
99
100 // So how can we go from a dynamic type to a concrete type?
101 // There are two ways:
102
103 // 1. Using `PartialReflect::apply`.
104 {
105 // If you know the type at compile time, you can construct a new value and apply the dynamic
106 // value to it.
107 let mut value = Player::default();
108 value.apply(deserialized.as_ref());
109 assert_eq!(value.id, 123);
110
111 // If you don't know the type at compile time, you need a dynamic way of constructing
112 // an instance of the type. One such way is to use the `ReflectDefault` type data.
113 let reflect_default = registration
114 .data::<ReflectDefault>()
115 .expect("`ReflectDefault` should be registered");
116
117 let mut value: Box<dyn Reflect> = reflect_default.default();
118 value.apply(deserialized.as_ref());
119
120 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
121 assert_eq!(identifiable.id(), 123);
122 }
123
124 // 2. Using `FromReflect`
125 {
126 // If you know the type at compile time, you can use the `FromReflect` trait to convert the
127 // dynamic value into the concrete type directly.
128 let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap();
129 assert_eq!(value.id, 123);
130
131 // If you don't know the type at compile time, you can use the `ReflectFromReflect` type data
132 // to perform the conversion dynamically.
133 let reflect_from_reflect = registration
134 .data::<ReflectFromReflect>()
135 .expect("`ReflectFromReflect` should be registered");
136
137 let value: Box<dyn Reflect> = reflect_from_reflect
138 .from_reflect(deserialized.as_ref())
139 .unwrap();
140 let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
141 assert_eq!(identifiable.id(), 123);
142 }
143
144 // Lastly, while dynamic types are commonly generated via reflection methods like
145 // `PartialReflect::to_dynamic` or via the reflection deserializers,
146 // you can also construct them manually.
147 let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
148
149 // This is useful when you just need to apply some subset of changes to a type.
150 let mut my_list: Vec<u32> = Vec::new();
151 my_list.apply(&my_dynamic_list);
152 assert_eq!(my_list, vec![1, 2, 3]);
153
154 // And if you want it to actually proxy a type, you can configure it to do that as well:
155 assert!(!my_dynamic_list
156 .as_partial_reflect()
157 .represents::<Vec<u32>>());
158 my_dynamic_list.set_represented_type(Some(<Vec<u32>>::type_info()));
159 assert!(my_dynamic_list
160 .as_partial_reflect()
161 .represents::<Vec<u32>>());
162
163 // ============================= REFERENCE ============================= //
164 // For reference, here are all the available dynamic types:
165
166 // 1. `DynamicTuple`
167 {
168 let mut dynamic_tuple = DynamicTuple::default();
169 dynamic_tuple.insert(1u32);
170 dynamic_tuple.insert(2u32);
171 dynamic_tuple.insert(3u32);
172
173 let mut my_tuple: (u32, u32, u32) = (0, 0, 0);
174 my_tuple.apply(&dynamic_tuple);
175 assert_eq!(my_tuple, (1, 2, 3));
176 }
177
178 // 2. `DynamicArray`
179 {
180 let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);
181
182 let mut my_array = [0u32; 3];
183 my_array.apply(&dynamic_array);
184 assert_eq!(my_array, [1, 2, 3]);
185 }
186
187 // 3. `DynamicList`
188 {
189 let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
190
191 let mut my_list: Vec<u32> = Vec::new();
192 my_list.apply(&dynamic_list);
193 assert_eq!(my_list, vec![1, 2, 3]);
194 }
195
196 // 4. `DynamicSet`
197 {
198 let mut dynamic_set = DynamicSet::from_iter(["x", "y", "z"]);
199 assert!(dynamic_set.contains(&"x"));
200
201 dynamic_set.remove(&"y");
202
203 let mut my_set: HashSet<&str> = HashSet::default();
204 my_set.apply(&dynamic_set);
205 assert_eq!(my_set, HashSet::from_iter(["x", "z"]));
206 }
207
208 // 5. `DynamicMap`
209 {
210 let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);
211
212 let mut my_map: HashMap<&str, u32> = HashMap::default();
213 my_map.apply(&dynamic_map);
214 assert_eq!(my_map.get("x"), Some(&1));
215 assert_eq!(my_map.get("y"), Some(&2));
216 assert_eq!(my_map.get("z"), Some(&3));
217 }
218
219 // 6. `DynamicStruct`
220 {
221 #[derive(Reflect, Default, Debug, PartialEq)]
222 struct MyStruct {
223 x: u32,
224 y: u32,
225 z: u32,
226 }
227
228 let mut dynamic_struct = DynamicStruct::default();
229 dynamic_struct.insert("x", 1u32);
230 dynamic_struct.insert("y", 2u32);
231 dynamic_struct.insert("z", 3u32);
232
233 let mut my_struct = MyStruct::default();
234 my_struct.apply(&dynamic_struct);
235 assert_eq!(my_struct, MyStruct { x: 1, y: 2, z: 3 });
236 }
237
238 // 7. `DynamicTupleStruct`
239 {
240 #[derive(Reflect, Default, Debug, PartialEq)]
241 struct MyTupleStruct(u32, u32, u32);
242
243 let mut dynamic_tuple_struct = DynamicTupleStruct::default();
244 dynamic_tuple_struct.insert(1u32);
245 dynamic_tuple_struct.insert(2u32);
246 dynamic_tuple_struct.insert(3u32);
247
248 let mut my_tuple_struct = MyTupleStruct::default();
249 my_tuple_struct.apply(&dynamic_tuple_struct);
250 assert_eq!(my_tuple_struct, MyTupleStruct(1, 2, 3));
251 }
252
253 // 8. `DynamicEnum`
254 {
255 #[derive(Reflect, Default, Debug, PartialEq)]
256 enum MyEnum {
257 #[default]
258 Empty,
259 Xyz(u32, u32, u32),
260 }
261
262 let mut values = DynamicTuple::default();
263 values.insert(1u32);
264 values.insert(2u32);
265 values.insert(3u32);
266
267 let dynamic_variant = DynamicVariant::Tuple(values);
268 let dynamic_enum = DynamicEnum::new("Xyz", dynamic_variant);
269
270 let mut my_enum = MyEnum::default();
271 my_enum.apply(&dynamic_enum);
272 assert_eq!(my_enum, MyEnum::Xyz(1, 2, 3));
273 }
274}