#[macro_export]
macro_rules! ketos_args {
( $args:expr , ( $( $ty:ty ),* ) ) => { {
let args: &[$crate::value::Value] = $args;
let n_args = args.len();
let expected = 0 $( + { stringify!($ty); 1 } )*;
if n_args != expected {
return Err(From::from($crate::exec::ExecError::ArityError{
name: None,
expected: $crate::function::Arity::Exact(expected as u32),
found: n_args as u32,
}));
}
let mut _iter = args.iter();
( $( {
let arg = _iter.next().unwrap();
<$ty as $crate::value::FromValueRef>::from_value_ref(arg)?
} , )* )
} };
( $args:expr , [ $( $ty:ty ),* ] ) => { {
let args: &[$crate::value::Value] = $args;
let n_args = args.len();
let max = 0 $( + { stringify!($ty); 1 })*;
if n_args > max {
return Err(From::from($crate::exec::ExecError::ArityError{
name: None,
expected: $crate::function::Arity::Range(0, max as u32),
found: n_args as u32,
}));
}
let mut _iter = args.iter();
( $( {
match _iter.next() {
Some(arg) => Some(<$ty as
$crate::value::FromValueRef>::from_value_ref(arg)?),
None => None
}
} , )* )
} };
( $args:expr , ( $( $r_ty:ty ),* [ $( $o_ty:ty ),* ] ) ) => { {
let args: &[$crate::value::Value] = $args;
let n_args = args.len();
let min = 0 $( + { stringify!($r_ty); 1 })*;
let optional = 0 $( + { stringify!($o_ty); 1 })*;
let max = min + optional;
if n_args < min || n_args > max {
return Err(From::from($crate::exec::ExecError::ArityError{
name: None,
expected: $crate::function::Arity::Range(
min as u32, max as u32),
found: n_args as u32,
}));
}
let mut _iter = args.iter();
( $( {
let arg = _iter.next().unwrap();
<$r_ty as $crate::value::FromValueRef>::from_value_ref(arg)?
} , )*
$( {
match _iter.next() {
Some(arg) => Some(<$o_ty as
$crate::value::FromValueRef>::from_value_ref(arg)?),
None => None
}
} , )* )
} };
}
#[cfg(test)]
mod test {
use crate::error::Error;
#[test]
fn test_args() {
let args = [1.into(), "sup".into(), (2, 'a').into()];
let f = || -> Result<(), Error> {
let (a, b, (c, d)) = ketos_args!(&args, (i32, &str, (i32, char)));
assert_eq!(a, 1);
assert_eq!(b, "sup");
assert_eq!(c, 2);
assert_eq!(d, 'a');
Ok(())
};
f().unwrap();
}
#[test]
fn test_empty_args() {
let args = [];
let f = || -> Result<(), Error> {
let () = ketos_args!(&args, ());
ketos_args!(&args, ());
Ok(())
};
f().unwrap();
}
#[test]
fn test_one_arg() {
let args = [1.into()];
let f = || -> Result<(), Error> {
let (a,) = ketos_args!(&args, (i32));
assert_eq!(a, 1);
let (a,) = ketos_args!(&args, [ i32 ]);
assert_eq!(a, Some(1));
Ok(())
};
f().unwrap();
}
#[test]
fn test_optional_args() {
let args = [1.into(), 2.into(), 3.into()];
let f = || -> Result<(), Error> {
let (a, b, c, d) = ketos_args!(&args, (i32, i32 [ i32, i32 ]));
assert_eq!(a, 1);
assert_eq!(b, 2);
assert_eq!(c, Some(3));
assert_eq!(d, None);
let (a, b, c, d) = ketos_args!(&args, [ i32, i32, i32, i32 ]);
assert_eq!(a, Some(1));
assert_eq!(b, Some(2));
assert_eq!(c, Some(3));
assert_eq!(d, None);
Ok(())
};
f().unwrap();
}
}