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
```
This commit is contained in:
Gino Valente 2024-09-20 12:14:57 -07:00 committed by GitHub
parent 5484d2d6f8
commit ebb57c5511
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -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<FunctionResult<'a>> {
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::<i32>(), 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::<i32>(), Some(&100));
}
#[test]
fn should_error_on_missing_name() {
let foo = || -> i32 { 123 };