bevy_reflect/func/
function.rs

1use crate::{
2    func::{
3        args::{ArgCount, ArgList},
4        DynamicFunction, FunctionInfo, FunctionResult,
5    },
6    PartialReflect,
7};
8use alloc::borrow::Cow;
9use 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
38pub 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)]
71mod 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}