ArgValue

Enum ArgValue 

Source
pub enum ArgValue<'a> {
    Owned(Box<dyn PartialReflect>),
    Ref(&'a (dyn PartialReflect + 'static)),
    Mut(&'a mut (dyn PartialReflect + 'static)),
}
Available on crate feature functions only.
Expand description

Represents an argument that can be passed to a DynamicFunction or DynamicFunctionMut.

Variants§

§

Owned(Box<dyn PartialReflect>)

An owned argument.

§

Ref(&'a (dyn PartialReflect + 'static))

An immutable reference argument.

§

Mut(&'a mut (dyn PartialReflect + 'static))

A mutable reference argument.

Methods from Deref<Target = dyn PartialReflect>§

Source

pub fn represents<T>(&self) -> bool
where T: Reflect + TypePath,

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?
examples/reflection/dynamic_types.rs (line 81)
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, &registry)
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}
Source

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?
examples/reflection/reflection_types.rs (line 49)
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
Hide additional examples
examples/reflection/function_reflection.rs (line 162)
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}
examples/reflection/dynamic_types.rs (line 65)
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, &registry)
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}

Trait Implementations§

Source§

impl<'a> Debug for ArgValue<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl<'a> Deref for ArgValue<'a>

Source§

type Target = dyn PartialReflect

The resulting type after dereferencing.
Source§

fn deref(&self) -> &<ArgValue<'a> as Deref>::Target

Dereferences the value.

Auto Trait Implementations§

§

impl<'a> Freeze for ArgValue<'a>

§

impl<'a> !RefUnwindSafe for ArgValue<'a>

§

impl<'a> Send for ArgValue<'a>

§

impl<'a> Sync for ArgValue<'a>

§

impl<'a> Unpin for ArgValue<'a>

§

impl<'a> !UnwindSafe for ArgValue<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, U> AsBindGroupShaderType<U> for T
where U: ShaderType, &'a T: for<'a> Into<U>,

Source§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U

Return the T ShaderType for self. When used in AsBindGroup derives, it is safe to assume that all images in self exist.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

impl<T> Identity for T
where T: ?Sized,

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
Source§

impl<T> InitializeFromFunction<T> for T

Source§

fn initialize_from_function(f: fn() -> T) -> T

Create an instance of this type from an initialization function
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoResult<T> for T

Source§

fn into_result(self) -> Result<T, RunSystemError>

Converts this type into the system output type.
Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<A> Is for A
where A: Any,

Source§

fn is<T>() -> bool
where T: Any,

Checks if the current type “is” another type, using a TypeId equality comparison. This is most useful in the context of generic logic. Read more
Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<Ret> SpawnIfAsync<(), Ret> for Ret

Source§

fn spawn(self) -> Ret

Spawn the value into the dioxus runtime if it is an async block
Source§

impl<T, O> SuperFrom<T> for O
where O: From<T>,

Source§

fn super_from(input: T) -> O

Convert from a type to another type.
Source§

impl<T, O, M> SuperInto<O, M> for T
where O: SuperFrom<T, M>,

Source§

fn super_into(self) -> O

Convert from a type to another type.
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ConditionalSend for T
where T: Send,

Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> Settings for T
where T: 'static + Send + Sync,

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,