Added Arg::is

Allows for manually defining basic generic function reflection
This commit is contained in:
Gino Valente 2024-09-02 12:36:45 -07:00
parent 14cc62c9c7
commit 85482b393a
3 changed files with 88 additions and 1 deletions

View File

@ -183,6 +183,14 @@ impl<'a> Arg<'a> {
}
}
}
/// Returns `true` if the argument is of type `T`.
pub fn is<T: TypePath>(&self) -> bool {
self.value
.try_as_reflect()
.map(<dyn Reflect>::is::<T>)
.unwrap_or_default()
}
}
/// Represents an argument that can be passed to a [`DynamicFunction`] or [`DynamicFunctionMut`].

View File

@ -328,7 +328,7 @@ impl<'env> IntoFunctionMut<'env, ()> for DynamicFunction<'env> {
#[cfg(test)]
mod tests {
use super::*;
use crate::func::IntoReturn;
use crate::func::{FunctionInfo, IntoReturn};
#[test]
fn should_overwrite_function_name() {
@ -434,4 +434,46 @@ mod tests {
let value = factorial.call(args).unwrap().unwrap_owned();
assert_eq!(value.try_take::<i32>().unwrap(), 120);
}
#[test]
fn should_allow_creating_manual_generic_dynamic_function() {
let func = DynamicFunction::new(
|mut args| {
let a = args.take_arg()?;
let b = args.take_arg()?;
if a.is::<i32>() {
let a = a.take::<i32>()?;
let b = b.take::<i32>()?;
Ok((a + b).into_return())
} else {
let a = a.take::<f32>()?;
let b = b.take::<f32>()?;
Ok((a + b).into_return())
}
},
vec![
FunctionInfo::named("add::<i32>")
.with_arg::<i32>("a")
.with_arg::<i32>("b")
.with_return::<i32>(),
FunctionInfo::named("add::<f32>")
.with_arg::<f32>("a")
.with_arg::<f32>("b")
.with_return::<f32>(),
],
);
assert!(func.name().is_none());
let func = func.with_name("add");
assert_eq!(func.name().unwrap(), "add");
let args = ArgList::default().push_owned(25_i32).push_owned(75_i32);
let result = func.call(args).unwrap().unwrap_owned();
assert_eq!(result.try_take::<i32>().unwrap(), 100);
let args = ArgList::default().push_owned(25.0_f32).push_owned(75.0_f32);
let result = func.call(args).unwrap().unwrap_owned();
assert_eq!(result.try_take::<f32>().unwrap(), 100.0);
}
}

View File

@ -276,6 +276,7 @@ impl<'env> IntoFunctionMut<'env, ()> for DynamicFunctionMut<'env> {
#[cfg(test)]
mod tests {
use super::*;
use crate::func::{FunctionInfo, IntoReturn};
#[test]
fn should_overwrite_function_name() {
@ -323,4 +324,40 @@ mod tests {
}
));
}
#[test]
fn should_allow_creating_manual_generic_dynamic_function_mut() {
let mut total = 0_i32;
let func = DynamicFunctionMut::new(
|mut args| {
let value = args.take_arg()?;
if value.is::<i32>() {
let value = value.take::<i32>()?;
total += value;
} else {
let value = value.take::<i16>()?;
total += value as i32;
}
Ok(().into_return())
},
vec![
FunctionInfo::named("add::<i32>").with_arg::<i32>("value"),
FunctionInfo::named("add::<i16>").with_arg::<i16>("value"),
],
);
assert!(func.name().is_none());
let mut func = func.with_name("add");
assert_eq!(func.name().unwrap(), "add");
let args = ArgList::default().push_owned(25_i32);
func.call(args).unwrap();
let args = ArgList::default().push_owned(75_i16);
func.call(args).unwrap();
drop(func);
assert_eq!(total, 100);
}
}