Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/func/function.rs
6599 views
1
use crate::{
2
func::{
3
args::{ArgCount, ArgList},
4
DynamicFunction, FunctionInfo, FunctionResult,
5
},
6
PartialReflect,
7
};
8
use alloc::borrow::Cow;
9
use core::fmt::Debug;
10
11
/// A trait used to power [function-like] operations via [reflection].
12
///
13
/// This trait allows types to be called like regular functions
14
/// with [`Reflect`]-based [arguments] and return values.
15
///
16
/// By default, this trait is currently only implemented for [`DynamicFunction`],
17
/// however, it is possible to implement this trait for custom function-like types.
18
///
19
/// # Example
20
///
21
/// ```
22
/// # use bevy_reflect::func::{IntoFunction, ArgList, Function};
23
/// fn add(a: i32, b: i32) -> i32 {
24
/// a + b
25
/// }
26
///
27
/// let func: Box<dyn Function> = Box::new(add.into_function());
28
/// let args = ArgList::new().with_owned(25_i32).with_owned(75_i32);
29
/// let value = func.reflect_call(args).unwrap().unwrap_owned();
30
/// assert_eq!(value.try_take::<i32>().unwrap(), 100);
31
/// ```
32
///
33
/// [function-like]: crate::func
34
/// [reflection]: crate::Reflect
35
/// [`Reflect`]: crate::Reflect
36
/// [arguments]: crate::func::args
37
/// [`DynamicFunction`]: crate::func::DynamicFunction
38
pub trait Function: PartialReflect + Debug {
39
/// The name of the function, if any.
40
///
41
/// For [`DynamicFunctions`] created using [`IntoFunction`],
42
/// the default name will always be the full path to the function as returned by [`core::any::type_name`],
43
/// unless the function is a closure, anonymous function, or function pointer,
44
/// in which case the name will be `None`.
45
///
46
/// [`DynamicFunctions`]: crate::func::DynamicFunction
47
/// [`IntoFunction`]: crate::func::IntoFunction
48
fn name(&self) -> Option<&Cow<'static, str>>;
49
50
/// Returns the number of arguments the function expects.
51
///
52
/// For [overloaded] functions that can have a variable number of arguments,
53
/// this will contain the full set of counts for all signatures.
54
///
55
/// [overloaded]: crate::func#overloading-functions
56
fn arg_count(&self) -> ArgCount {
57
self.info().arg_count()
58
}
59
60
/// The [`FunctionInfo`] for this function.
61
fn info(&self) -> &FunctionInfo;
62
63
/// Call this function with the given arguments.
64
fn reflect_call<'a>(&self, args: ArgList<'a>) -> FunctionResult<'a>;
65
66
/// Creates a new [`DynamicFunction`] from this function.
67
fn to_dynamic_function(&self) -> DynamicFunction<'static>;
68
}
69
70
#[cfg(test)]
71
mod tests {
72
use super::*;
73
use crate::func::IntoFunction;
74
use alloc::boxed::Box;
75
76
#[test]
77
fn should_call_dyn_function() {
78
fn add(a: i32, b: i32) -> i32 {
79
a + b
80
}
81
82
let func: Box<dyn Function> = Box::new(add.into_function());
83
let args = ArgList::new().with_owned(25_i32).with_owned(75_i32);
84
let value = func.reflect_call(args).unwrap().unwrap_owned();
85
assert_eq!(value.try_take::<i32>().unwrap(), 100);
86
}
87
}
88
89