pub struct ArgList<'a> { /* private fields */ }functions only.Expand description
A list of arguments that can be passed to a DynamicFunction or DynamicFunctionMut.
§Example
let foo = 123;
let bar = 456;
let mut baz = 789;
let args = ArgList::new()
// Push an owned argument
.with_owned(foo)
// Push an owned and boxed argument
.with_boxed(Box::new(foo))
// Push a reference argument
.with_ref(&bar)
// Push a mutable reference argument
.with_mut(&mut baz)
// Push a manually constructed argument
.with_arg(ArgValue::Ref(&3.14));Implementations§
Source§impl<'a> ArgList<'a>
impl<'a> ArgList<'a>
Sourcepub fn new() -> ArgList<'a>
pub fn new() -> ArgList<'a>
Create a new empty list of arguments.
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 push_arg(&mut self, arg: ArgValue<'a>)
pub fn push_arg(&mut self, arg: ArgValue<'a>)
Push an ArgValue onto the list.
If an argument was previously removed from the beginning of the list, this method will also re-index the list.
Sourcepub fn push_ref(&mut self, arg: &'a (dyn PartialReflect + 'static))
pub fn push_ref(&mut self, arg: &'a (dyn PartialReflect + 'static))
Push an ArgValue::Ref onto the list with the given reference.
If an argument was previously removed from the beginning of the list, this method will also re-index the list.
Sourcepub fn push_mut(&mut self, arg: &'a mut (dyn PartialReflect + 'static))
pub fn push_mut(&mut self, arg: &'a mut (dyn PartialReflect + 'static))
Push an ArgValue::Mut onto the list with the given mutable reference.
If an argument was previously removed from the beginning of the list, this method will also re-index the list.
Sourcepub fn push_owned(&mut self, arg: impl PartialReflect)
pub fn push_owned(&mut self, arg: impl PartialReflect)
Push an ArgValue::Owned onto the list with the given owned value.
If an argument was previously removed from the beginning of the list, this method will also re-index the list.
Sourcepub fn push_boxed(&mut self, arg: Box<dyn PartialReflect>)
pub fn push_boxed(&mut self, arg: Box<dyn PartialReflect>)
Push an ArgValue::Owned onto the list with the given boxed value.
If an argument was previously removed from the beginning of the list, this method will also re-index the list.
Sourcepub fn with_arg(self, arg: ArgValue<'a>) -> ArgList<'a>
pub fn with_arg(self, arg: ArgValue<'a>) -> ArgList<'a>
Push an ArgValue onto the list.
If an argument was previously removed from the beginning of the list, this method will also re-index the list.
Sourcepub fn with_ref(self, arg: &'a (dyn PartialReflect + 'static)) -> ArgList<'a>
pub fn with_ref(self, arg: &'a (dyn PartialReflect + 'static)) -> ArgList<'a>
Push an ArgValue::Ref onto the list with the given reference.
If an argument was previously removed from the beginning of the list, this method will also re-index the list.
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 with_mut(
self,
arg: &'a mut (dyn PartialReflect + 'static),
) -> ArgList<'a>
pub fn with_mut( self, arg: &'a mut (dyn PartialReflect + 'static), ) -> ArgList<'a>
Push an ArgValue::Mut onto the list with the given mutable reference.
If an argument was previously removed from the beginning of the list, this method will also re-index the list.
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 with_owned(self, arg: impl PartialReflect) -> ArgList<'a>
pub fn with_owned(self, arg: impl PartialReflect) -> ArgList<'a>
Push an ArgValue::Owned onto the list with the given owned value.
If an argument was previously removed from the beginning of the list, this method will also re-index the list.
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 with_boxed(self, arg: Box<dyn PartialReflect>) -> ArgList<'a>
pub fn with_boxed(self, arg: Box<dyn PartialReflect>) -> ArgList<'a>
Push an ArgValue::Owned onto the list with the given boxed value.
If an argument was previously removed from the beginning of the list, this method will also re-index the list.
Sourcepub fn take_arg(&mut self) -> Result<Arg<'a>, ArgError>
pub fn take_arg(&mut self) -> Result<Arg<'a>, ArgError>
Remove the first argument in the list and return it.
It’s generally preferred to use Self::take instead of this method
as it provides a more ergonomic way to immediately downcast the argument.
Sourcepub fn take<T>(&mut self) -> Result<<T as FromArg>::This<'a>, ArgError>where
T: FromArg,
pub fn take<T>(&mut self) -> Result<<T as FromArg>::This<'a>, ArgError>where
T: FromArg,
Remove the first argument in the list and return Ok(T::This).
If the list is empty or the FromArg::from_arg call fails, returns an error.
§Example
let a = 1u32;
let b = 2u32;
let mut c = 3u32;
let mut args = ArgList::new().with_owned(a).with_ref(&b).with_mut(&mut c);
let a = args.take::<u32>().unwrap();
assert_eq!(a, 1);
let b = args.take::<&u32>().unwrap();
assert_eq!(*b, 2);
let c = args.take::<&mut u32>().unwrap();
assert_eq!(*c, 3);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 take_owned<T>(&mut self) -> Result<T, ArgError>
pub fn take_owned<T>(&mut self) -> Result<T, ArgError>
Remove the first argument in the list and return Ok(T) if the argument is ArgValue::Owned.
If the list is empty or the argument is not owned, returns an error.
It’s generally preferred to use Self::take instead of this method.
§Example
let value = 123u32;
let mut args = ArgList::new().with_owned(value);
let value = args.take_owned::<u32>().unwrap();
assert_eq!(value, 123);Sourcepub fn take_ref<T>(&mut self) -> Result<&'a T, ArgError>
pub fn take_ref<T>(&mut self) -> Result<&'a T, ArgError>
Remove the first argument in the list and return Ok(&T) if the argument is ArgValue::Ref.
If the list is empty or the argument is not a reference, returns an error.
It’s generally preferred to use Self::take instead of this method.
§Example
let value = 123u32;
let mut args = ArgList::new().with_ref(&value);
let value = args.take_ref::<u32>().unwrap();
assert_eq!(*value, 123);Sourcepub fn take_mut<T>(&mut self) -> Result<&'a mut T, ArgError>
pub fn take_mut<T>(&mut self) -> Result<&'a mut T, ArgError>
Remove the first argument in the list and return Ok(&mut T) if the argument is ArgValue::Mut.
If the list is empty or the argument is not a mutable reference, returns an error.
It’s generally preferred to use Self::take instead of this method.
§Example
let mut value = 123u32;
let mut args = ArgList::new().with_mut(&mut value);
let value = args.take_mut::<u32>().unwrap();
assert_eq!(*value, 123);Sourcepub fn pop_arg(&mut self) -> Result<Arg<'a>, ArgError>
pub fn pop_arg(&mut self) -> Result<Arg<'a>, ArgError>
Remove the last argument in the list and return it.
It’s generally preferred to use Self::pop instead of this method
as it provides a more ergonomic way to immediately downcast the argument.
Sourcepub fn pop<T>(&mut self) -> Result<<T as FromArg>::This<'a>, ArgError>where
T: FromArg,
pub fn pop<T>(&mut self) -> Result<<T as FromArg>::This<'a>, ArgError>where
T: FromArg,
Remove the last argument in the list and return Ok(T::This).
If the list is empty or the FromArg::from_arg call fails, returns an error.
§Example
let a = 1u32;
let b = 2u32;
let mut c = 3u32;
let mut args = ArgList::new().with_owned(a).with_ref(&b).with_mut(&mut c);
let c = args.pop::<&mut u32>().unwrap();
assert_eq!(*c, 3);
let b = args.pop::<&u32>().unwrap();
assert_eq!(*b, 2);
let a = args.pop::<u32>().unwrap();
assert_eq!(a, 1);Sourcepub fn pop_owned<T>(&mut self) -> Result<T, ArgError>
pub fn pop_owned<T>(&mut self) -> Result<T, ArgError>
Remove the last argument in the list and return Ok(T) if the argument is ArgValue::Owned.
If the list is empty or the argument is not owned, returns an error.
It’s generally preferred to use Self::pop instead of this method.
§Example
let value = 123u32;
let mut args = ArgList::new().with_owned(value);
let value = args.pop_owned::<u32>().unwrap();
assert_eq!(value, 123);Sourcepub fn pop_ref<T>(&mut self) -> Result<&'a T, ArgError>
pub fn pop_ref<T>(&mut self) -> Result<&'a T, ArgError>
Remove the last argument in the list and return Ok(&T) if the argument is ArgValue::Ref.
If the list is empty or the argument is not a reference, returns an error.
It’s generally preferred to use Self::pop instead of this method.
§Example
let value = 123u32;
let mut args = ArgList::new().with_ref(&value);
let value = args.pop_ref::<u32>().unwrap();
assert_eq!(*value, 123);Sourcepub fn pop_mut<T>(&mut self) -> Result<&'a mut T, ArgError>
pub fn pop_mut<T>(&mut self) -> Result<&'a mut T, ArgError>
Remove the last argument in the list and return Ok(&mut T) if the argument is ArgValue::Mut.
If the list is empty or the argument is not a mutable reference, returns an error.
It’s generally preferred to use Self::pop instead of this method.
§Example
let mut value = 123u32;
let mut args = ArgList::new().with_mut(&mut value);
let value = args.pop_mut::<u32>().unwrap();
assert_eq!(*value, 123);Trait Implementations§
Source§impl From<&ArgList<'_>> for ArgumentSignature
impl From<&ArgList<'_>> for ArgumentSignature
Source§fn from(args: &ArgList<'_>) -> ArgumentSignature
fn from(args: &ArgList<'_>) -> ArgumentSignature
Auto Trait Implementations§
impl<'a> Freeze for ArgList<'a>
impl<'a> !RefUnwindSafe for ArgList<'a>
impl<'a> Send for ArgList<'a>
impl<'a> Sync for ArgList<'a>
impl<'a> Unpin for ArgList<'a>
impl<'a> UnsafeUnpin for ArgList<'a>
impl<'a> !UnwindSafe for ArgList<'a>
Blanket Implementations§
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T ShaderType for self. When used in AsBindGroup
derives, it is safe to assume that all images in self exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&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 Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&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
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
Source§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Creates Self using default().
Source§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> InitializeFromFunction<T> for T
impl<T> InitializeFromFunction<T> for T
Source§fn initialize_from_function(f: fn() -> T) -> T
fn initialize_from_function(f: fn() -> T) -> T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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 moreSource§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
Source§fn into_result(self) -> Result<T, RunSystemError>
fn into_result(self) -> Result<T, RunSystemError>
Source§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
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
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
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
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian().Source§impl<Ret> SpawnIfAsync<(), Ret> for Ret
impl<Ret> SpawnIfAsync<(), Ret> for Ret
Source§impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
Source§fn super_from(input: T) -> O
fn super_from(input: T) -> O
Source§impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
Source§fn super_into(self) -> O
fn super_into(self) -> O
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.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
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.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
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.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
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.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
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.