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}