bevy_reflect/func/
function.rs

1use crate::{
2    func::{ArgList, DynamicFunction, FunctionInfo, FunctionResult},
3    PartialReflect,
4};
5use alloc::borrow::Cow;
6use core::fmt::Debug;
7
8/// A trait used to power [function-like] operations via [reflection].
9///
10/// This trait allows types to be called like regular functions
11/// with [`Reflect`]-based [arguments] and return values.
12///
13/// By default, this trait is currently only implemented for [`DynamicFunction`],
14/// however, it is possible to implement this trait for custom function-like types.
15///
16/// # Example
17///
18/// ```
19/// # use bevy_reflect::func::{IntoFunction, ArgList, Function};
20/// fn add(a: i32, b: i32) -> i32 {
21///    a + b
22/// }
23///
24/// let func: Box<dyn Function> = Box::new(add.into_function());
25/// let args = ArgList::new().push_owned(25_i32).push_owned(75_i32);
26/// let value = func.reflect_call(args).unwrap().unwrap_owned();
27/// assert_eq!(value.try_take::<i32>().unwrap(), 100);
28/// ```
29///
30/// [function-like]: crate::func
31/// [reflection]: crate::Reflect
32/// [`Reflect`]: crate::Reflect
33/// [arguments]: crate::func::args
34/// [`DynamicFunction`]: crate::func::DynamicFunction
35pub trait Function: PartialReflect + Debug {
36    /// The name of the function, if any.
37    ///
38    /// For [`DynamicFunctions`] created using [`IntoFunction`],
39    /// the default name will always be the full path to the function as returned by [`std::any::type_name`],
40    /// unless the function is a closure, anonymous function, or function pointer,
41    /// in which case the name will be `None`.
42    ///
43    /// [`DynamicFunctions`]: crate::func::DynamicFunction
44    /// [`IntoFunction`]: crate::func::IntoFunction
45    fn name(&self) -> Option<&Cow<'static, str>> {
46        self.info().name()
47    }
48
49    /// The number of arguments this function accepts.
50    fn arg_count(&self) -> usize {
51        self.info().arg_count()
52    }
53
54    /// The [`FunctionInfo`] for this function.
55    fn info(&self) -> &FunctionInfo;
56
57    /// Call this function with the given arguments.
58    fn reflect_call<'a>(&self, args: ArgList<'a>) -> FunctionResult<'a>;
59
60    /// Clone this function into a [`DynamicFunction`].
61    fn clone_dynamic(&self) -> DynamicFunction<'static>;
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    use crate::func::IntoFunction;
68
69    #[test]
70    fn should_call_dyn_function() {
71        fn add(a: i32, b: i32) -> i32 {
72            a + b
73        }
74
75        let func: Box<dyn Function> = Box::new(add.into_function());
76        let args = ArgList::new().push_owned(25_i32).push_owned(75_i32);
77        let value = func.reflect_call(args).unwrap().unwrap_owned();
78        assert_eq!(value.try_take::<i32>().unwrap(), 100);
79    }
80}