From ebb57c55116db14844fd89ad82d410dbf541073c Mon Sep 17 00:00:00 2001 From: Gino Valente <49806985+MrGVSV@users.noreply.github.com> Date: Fri, 20 Sep 2024 12:14:57 -0700 Subject: [PATCH] bevy_reflect: Add `FunctionRegistry::call` (#15148) # Objective There may be times where a function in the `FunctionRegistry` doesn't need to be fully retrieved. A user may just need to call it with a set of arguments. We should provide a shortcut for doing this. ## Solution Add the `FunctionRegistry::call` method to directly call a function in the registry with the given name and arguments. ## Testing You can test locally by running: ``` cargo test --package bevy_reflect --all-features ``` --- crates/bevy_reflect/src/func/registry.rs | 33 +++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/crates/bevy_reflect/src/func/registry.rs b/crates/bevy_reflect/src/func/registry.rs index 87f66a070d..2c88ef509a 100644 --- a/crates/bevy_reflect/src/func/registry.rs +++ b/crates/bevy_reflect/src/func/registry.rs @@ -4,7 +4,9 @@ use std::sync::{Arc, PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard}; use bevy_utils::HashMap; -use crate::func::{DynamicFunction, FunctionRegistrationError, IntoFunction}; +use crate::func::{ + ArgList, DynamicFunction, FunctionRegistrationError, FunctionResult, IntoFunction, +}; /// A registry of [reflected functions]. /// @@ -282,6 +284,18 @@ impl FunctionRegistry { } } + /// Calls the function with the given [name] and [args]. + /// + /// Returns `None` if no function with the given name is registered. + /// Otherwise, returns the result of the function call. + /// + /// [name]: DynamicFunction::name + /// [args]: ArgList + pub fn call<'a>(&self, name: &str, args: ArgList<'a>) -> Option> { + let func = self.get(name)?; + Some(func.call(args)) + } + /// Get a reference to a registered function by [name]. /// /// [name]: DynamicFunction::name @@ -463,6 +477,23 @@ mod tests { assert_eq!(value.try_downcast_ref::(), Some(&321)); } + #[test] + fn should_call_function_via_registry() { + fn add(a: i32, b: i32) -> i32 { + a + b + } + + let mut registry = FunctionRegistry::default(); + registry.register(add).unwrap(); + + let args = ArgList::new().push_owned(25_i32).push_owned(75_i32); + let result = registry + .call(std::any::type_name_of_val(&add), args) + .unwrap(); + let value = result.unwrap().unwrap_owned(); + assert_eq!(value.try_downcast_ref::(), Some(&100)); + } + #[test] fn should_error_on_missing_name() { let foo = || -> i32 { 123 };