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