Path: blob/main/crates/bevy_reflect/src/func/into_function_mut.rs
6599 views
use crate::func::{DynamicFunctionMut, ReflectFnMut, TypedFunction};12/// A trait for types that can be converted into a [`DynamicFunctionMut`].3///4/// This trait is automatically implemented for any type that implements5/// [`ReflectFnMut`] and [`TypedFunction`].6///7/// This trait can be seen as a superset of [`IntoFunction`].8///9/// See the [module-level documentation] for more information.10///11/// # Trait Parameters12///13/// This trait has a `Marker` type parameter that is used to get around issues with14/// [unconstrained type parameters] when defining impls with generic arguments or return types.15/// This `Marker` can be any type, provided it doesn't conflict with other implementations.16///17/// Additionally, it has a lifetime parameter, `'env`, that is used to bound the lifetime of the function.18/// For named functions and some closures, this will end up just being `'static`,19/// however, closures that borrow from their environment will have a lifetime bound to that environment.20///21/// [`IntoFunction`]: crate::func::IntoFunction22/// [module-level documentation]: crate::func23/// [unconstrained type parameters]: https://doc.rust-lang.org/error_codes/E0207.html24pub trait IntoFunctionMut<'env, Marker> {25/// Converts [`Self`] into a [`DynamicFunctionMut`].26fn into_function_mut(self) -> DynamicFunctionMut<'env>;27}2829impl<'env, F, Marker1, Marker2> IntoFunctionMut<'env, (Marker1, Marker2)> for F30where31F: ReflectFnMut<'env, Marker1> + TypedFunction<Marker2> + 'env,32{33fn into_function_mut(mut self) -> DynamicFunctionMut<'env> {34DynamicFunctionMut::new(35move |args| self.reflect_call_mut(args),36Self::function_info(),37)38}39}4041#[cfg(test)]42mod tests {43use super::*;44use crate::func::{ArgList, IntoFunction};4546#[test]47fn should_create_dynamic_function_mut_from_closure() {48let c = 23;49let func = (|a: i32, b: i32| a + b + c).into_function();50let args = ArgList::new().with_owned(25_i32).with_owned(75_i32);51let result = func.call(args).unwrap().unwrap_owned();52assert_eq!(result.try_downcast_ref::<i32>(), Some(&123));53}5455#[test]56fn should_create_dynamic_function_mut_from_closure_with_mutable_capture() {57let mut total = 0;58let func = (|a: i32, b: i32| total = a + b).into_function_mut();59let args = ArgList::new().with_owned(25_i32).with_owned(75_i32);60func.call_once(args).unwrap();61assert_eq!(total, 100);62}6364#[test]65fn should_create_dynamic_function_mut_from_function() {66fn add(a: i32, b: i32) -> i32 {67a + b68}6970let mut func = add.into_function_mut();71let args = ArgList::new().with_owned(25_i32).with_owned(75_i32);72let result = func.call(args).unwrap().unwrap_owned();73assert_eq!(result.try_downcast_ref::<i32>(), Some(&100));74}7576#[test]77fn should_default_closure_name_to_none() {78let mut total = 0;79let func = (|a: i32, b: i32| total = a + b).into_function_mut();80assert!(func.name().is_none());81}82}838485