Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/func/into_function_mut.rs
6599 views
1
use crate::func::{DynamicFunctionMut, ReflectFnMut, TypedFunction};
2
3
/// A trait for types that can be converted into a [`DynamicFunctionMut`].
4
///
5
/// This trait is automatically implemented for any type that implements
6
/// [`ReflectFnMut`] and [`TypedFunction`].
7
///
8
/// This trait can be seen as a superset of [`IntoFunction`].
9
///
10
/// See the [module-level documentation] for more information.
11
///
12
/// # Trait Parameters
13
///
14
/// This trait has a `Marker` type parameter that is used to get around issues with
15
/// [unconstrained type parameters] when defining impls with generic arguments or return types.
16
/// This `Marker` can be any type, provided it doesn't conflict with other implementations.
17
///
18
/// Additionally, it has a lifetime parameter, `'env`, that is used to bound the lifetime of the function.
19
/// For named functions and some closures, this will end up just being `'static`,
20
/// however, closures that borrow from their environment will have a lifetime bound to that environment.
21
///
22
/// [`IntoFunction`]: crate::func::IntoFunction
23
/// [module-level documentation]: crate::func
24
/// [unconstrained type parameters]: https://doc.rust-lang.org/error_codes/E0207.html
25
pub trait IntoFunctionMut<'env, Marker> {
26
/// Converts [`Self`] into a [`DynamicFunctionMut`].
27
fn into_function_mut(self) -> DynamicFunctionMut<'env>;
28
}
29
30
impl<'env, F, Marker1, Marker2> IntoFunctionMut<'env, (Marker1, Marker2)> for F
31
where
32
F: ReflectFnMut<'env, Marker1> + TypedFunction<Marker2> + 'env,
33
{
34
fn into_function_mut(mut self) -> DynamicFunctionMut<'env> {
35
DynamicFunctionMut::new(
36
move |args| self.reflect_call_mut(args),
37
Self::function_info(),
38
)
39
}
40
}
41
42
#[cfg(test)]
43
mod tests {
44
use super::*;
45
use crate::func::{ArgList, IntoFunction};
46
47
#[test]
48
fn should_create_dynamic_function_mut_from_closure() {
49
let c = 23;
50
let func = (|a: i32, b: i32| a + b + c).into_function();
51
let args = ArgList::new().with_owned(25_i32).with_owned(75_i32);
52
let result = func.call(args).unwrap().unwrap_owned();
53
assert_eq!(result.try_downcast_ref::<i32>(), Some(&123));
54
}
55
56
#[test]
57
fn should_create_dynamic_function_mut_from_closure_with_mutable_capture() {
58
let mut total = 0;
59
let func = (|a: i32, b: i32| total = a + b).into_function_mut();
60
let args = ArgList::new().with_owned(25_i32).with_owned(75_i32);
61
func.call_once(args).unwrap();
62
assert_eq!(total, 100);
63
}
64
65
#[test]
66
fn should_create_dynamic_function_mut_from_function() {
67
fn add(a: i32, b: i32) -> i32 {
68
a + b
69
}
70
71
let mut func = add.into_function_mut();
72
let args = ArgList::new().with_owned(25_i32).with_owned(75_i32);
73
let result = func.call(args).unwrap().unwrap_owned();
74
assert_eq!(result.try_downcast_ref::<i32>(), Some(&100));
75
}
76
77
#[test]
78
fn should_default_closure_name_to_none() {
79
let mut total = 0;
80
let func = (|a: i32, b: i32| total = a + b).into_function_mut();
81
assert!(func.name().is_none());
82
}
83
}
84
85