rune/runtime/
guarded_args.rs

1use crate::alloc::Vec;
2use crate::runtime::Args;
3use crate::runtime::{Stack, UnsafeToValue, Value, VmResult};
4
5/// Trait for converting arguments onto the stack.
6///
7/// This can take references, because it is unsafe to call. And should only be
8/// implemented in contexts where it can be guaranteed that the references will
9/// not outlive the call.
10pub trait GuardedArgs {
11    /// Guard that when dropped will invalidate any values encoded.
12    type Guard;
13
14    /// Encode arguments onto a stack.
15    ///
16    /// # Safety
17    ///
18    /// This can encode references onto the stack. The caller must ensure that
19    /// the guard is dropped before any references which have been encoded are
20    /// no longer alive.
21    unsafe fn guarded_into_stack(self, stack: &mut Stack) -> VmResult<Self::Guard>;
22
23    /// Encode arguments into a vector.
24    ///
25    /// # Safety
26    ///
27    /// This can encode references into the vector. The caller must ensure that
28    /// the guard is dropped before any references which have been encoded are
29    /// no longer alive.
30    unsafe fn guarded_into_vec(self) -> VmResult<(Vec<Value>, Self::Guard)>;
31
32    /// The number of arguments.
33    fn count(&self) -> usize;
34}
35
36macro_rules! impl_into_args {
37    ($count:expr $(, $ty:ident $value:ident $_:expr)*) => {
38        impl<$($ty,)*> GuardedArgs for ($($ty,)*)
39        where
40            $($ty: UnsafeToValue,)*
41        {
42            type Guard = ($($ty::Guard,)*);
43
44            #[allow(unused)]
45            #[inline]
46            unsafe fn guarded_into_stack(self, stack: &mut Stack) -> VmResult<Self::Guard> {
47                let ($($value,)*) = self;
48                $(let $value = vm_try!($value.unsafe_to_value());)*
49                $(vm_try!(stack.push($value.0));)*
50                VmResult::Ok(($($value.1,)*))
51            }
52
53            #[allow(unused)]
54            #[inline]
55            unsafe fn guarded_into_vec(self) -> VmResult<(Vec<Value>, Self::Guard)> {
56                let ($($value,)*) = self;
57                $(let $value = vm_try!($value.unsafe_to_value());)*
58                let mut out = vm_try!(Vec::try_with_capacity($count));
59                $(vm_try!(out.try_push($value.0));)*
60                VmResult::Ok((out, ($($value.1,)*)))
61            }
62
63            #[inline]
64            fn count(&self) -> usize {
65                $count
66            }
67        }
68    };
69}
70
71repeat_macro!(impl_into_args);
72
73impl GuardedArgs for Vec<Value> {
74    type Guard = ();
75
76    #[inline]
77    unsafe fn guarded_into_stack(self, stack: &mut Stack) -> VmResult<Self::Guard> {
78        self.into_stack(stack)
79    }
80
81    #[inline]
82    unsafe fn guarded_into_vec(self) -> VmResult<(Vec<Value>, Self::Guard)> {
83        VmResult::Ok((self, ()))
84    }
85
86    #[inline]
87    fn count(&self) -> usize {
88        (self as &dyn Args).count()
89    }
90}
91
92#[cfg(feature = "alloc")]
93impl GuardedArgs for ::rust_alloc::vec::Vec<Value> {
94    type Guard = ();
95
96    #[inline]
97    unsafe fn guarded_into_stack(self, stack: &mut Stack) -> VmResult<Self::Guard> {
98        self.into_stack(stack)
99    }
100
101    #[inline]
102    unsafe fn guarded_into_vec(self) -> VmResult<(Vec<Value>, Self::Guard)> {
103        VmResult::Ok((vm_try!(Vec::try_from(self)), ()))
104    }
105
106    #[inline]
107    fn count(&self) -> usize {
108        self.len()
109    }
110}