runestick/
args.rs

1use crate::{Stack, Value, VmError};
2
3/// Trait for converting arguments onto the stack.
4pub trait Args {
5    /// Encode arguments onto a stack.
6    fn into_stack(self, stack: &mut crate::Stack) -> Result<(), crate::VmError>;
7
8    /// Convert arguments into a vector.
9    fn into_vec(self) -> Result<Vec<crate::Value>, crate::VmError>;
10
11    /// The number of arguments.
12    fn count(&self) -> usize;
13}
14
15macro_rules! impl_into_args {
16    () => {
17        impl_into_args!{@impl 0,}
18    };
19
20    ({$ty:ident, $value:ident, $count:expr}, $({$l_ty:ident, $l_value:ident, $l_count:expr},)*) => {
21        impl_into_args!{@impl $count, {$ty, $value, $count}, $({$l_ty, $l_value, $l_count},)*}
22        impl_into_args!{$({$l_ty, $l_value, $l_count},)*}
23    };
24
25    (@impl $count:expr, $({$ty:ident, $value:ident, $ignore_count:expr},)*) => {
26        impl<$($ty,)*> Args for ($($ty,)*)
27        where
28            $($ty: $crate::ToValue,)*
29        {
30            #[allow(unused)]
31            fn into_stack(self, stack: &mut $crate::Stack) -> Result<(), $crate::VmError> {
32                let ($($value,)*) = self;
33                $(stack.push($value.to_value()?);)*
34                Ok(())
35            }
36
37            #[allow(unused)]
38            fn into_vec(self) -> Result<Vec<$crate::Value>, $crate::VmError> {
39                let ($($value,)*) = self;
40                $(let $value = <$ty>::to_value($value)?;)*
41                Ok(vec![$($value,)*])
42            }
43
44            fn count(&self) -> usize {
45                $count
46            }
47        }
48    };
49}
50
51repeat_macro!(impl_into_args);
52
53impl Args for Vec<Value> {
54    fn into_stack(self, stack: &mut Stack) -> Result<(), VmError> {
55        for value in self {
56            stack.push(value);
57        }
58        Ok(())
59    }
60
61    fn into_vec(self) -> Result<Vec<Value>, VmError> {
62        Ok(self)
63    }
64
65    fn count(&self) -> usize {
66        self.len()
67    }
68}