rune/runtime/
args.rs
1use core::fmt;
2
3use crate::alloc::Vec;
4use crate::runtime::{GuardedArgs, Stack, ToValue, Value, VmResult};
5
6#[derive(Debug)]
7#[cfg_attr(test, derive(PartialEq))]
8pub(crate) struct DynArgsUsed;
9
10impl fmt::Display for DynArgsUsed {
11 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12 write!(f, "Dynamic arguments have already been used")
13 }
14}
15
16pub(crate) trait DynArgs {
18 fn push_to_stack(&mut self, stack: &mut Stack) -> VmResult<()>;
20
21 fn count(&self) -> usize;
23}
24
25impl DynArgs for () {
26 fn push_to_stack(&mut self, _: &mut Stack) -> VmResult<()> {
27 VmResult::Ok(())
28 }
29
30 fn count(&self) -> usize {
31 0
32 }
33}
34
35impl<T> DynArgs for Option<T>
36where
37 T: Args,
38{
39 fn push_to_stack(&mut self, stack: &mut Stack) -> VmResult<()> {
40 let Some(args) = self.take() else {
41 return VmResult::err(DynArgsUsed);
42 };
43
44 vm_try!(args.into_stack(stack));
45 VmResult::Ok(())
46 }
47
48 fn count(&self) -> usize {
49 self.as_ref().map_or(0, Args::count)
50 }
51}
52
53pub(crate) struct DynGuardedArgs<T>
54where
55 T: GuardedArgs,
56{
57 value: Option<T>,
58 guard: Option<T::Guard>,
59}
60
61impl<T> DynGuardedArgs<T>
62where
63 T: GuardedArgs,
64{
65 pub(crate) fn new(value: T) -> Self {
66 Self {
67 value: Some(value),
68 guard: None,
69 }
70 }
71}
72
73impl<T> DynArgs for DynGuardedArgs<T>
74where
75 T: GuardedArgs,
76{
77 fn push_to_stack(&mut self, stack: &mut Stack) -> VmResult<()> {
78 let Some(value) = self.value.take() else {
79 return VmResult::err(DynArgsUsed);
80 };
81
82 self.guard = unsafe { Some(vm_try!(GuardedArgs::guarded_into_stack(value, stack))) };
84
85 VmResult::Ok(())
86 }
87
88 fn count(&self) -> usize {
89 self.value.as_ref().map_or(0, GuardedArgs::count)
90 }
91}
92
93pub trait FixedArgs<const N: usize> {
95 fn into_array(self) -> VmResult<[Value; N]>;
97}
98
99pub trait Args {
101 fn into_stack(self, stack: &mut Stack) -> VmResult<()>;
103
104 fn try_into_vec(self) -> VmResult<Vec<Value>>;
106
107 fn count(&self) -> usize;
109}
110
111macro_rules! impl_into_args {
112 ($count:expr $(, $ty:ident $value:ident $_:expr)*) => {
113 impl<$($ty,)*> FixedArgs<$count> for ($($ty,)*)
114 where
115 $($ty: ToValue,)*
116 {
117 #[allow(unused)]
118 fn into_array(self) -> VmResult<[Value; $count]> {
119 let ($($value,)*) = self;
120 $(let $value = vm_try!($value.to_value());)*
121 VmResult::Ok([$($value),*])
122 }
123 }
124
125 impl<$($ty,)*> Args for ($($ty,)*)
126 where
127 $($ty: ToValue,)*
128 {
129 #[allow(unused)]
130 fn into_stack(self, stack: &mut Stack) -> VmResult<()> {
131 let ($($value,)*) = self;
132 $(vm_try!(stack.push(vm_try!($value.to_value())));)*
133 VmResult::Ok(())
134 }
135
136 #[allow(unused)]
137 fn try_into_vec(self) -> VmResult<Vec<Value>> {
138 let ($($value,)*) = self;
139 let mut vec = vm_try!(Vec::try_with_capacity($count));
140 $(vm_try!(vec.try_push(vm_try!(<$ty>::to_value($value))));)*
141 VmResult::Ok(vec)
142 }
143
144 #[inline]
145 fn count(&self) -> usize {
146 $count
147 }
148 }
149 };
150}
151
152repeat_macro!(impl_into_args);
153
154impl Args for Vec<Value> {
155 fn into_stack(self, stack: &mut Stack) -> VmResult<()> {
156 for value in self {
157 vm_try!(stack.push(value));
158 }
159
160 VmResult::Ok(())
161 }
162
163 #[inline]
164 fn try_into_vec(self) -> VmResult<Vec<Value>> {
165 VmResult::Ok(self)
166 }
167
168 #[inline]
169 fn count(&self) -> usize {
170 self.len()
171 }
172}
173
174#[cfg(feature = "alloc")]
175impl Args for ::rust_alloc::vec::Vec<Value> {
176 fn into_stack(self, stack: &mut Stack) -> VmResult<()> {
177 for value in self {
178 vm_try!(stack.push(value));
179 }
180
181 VmResult::Ok(())
182 }
183
184 #[inline]
185 fn try_into_vec(self) -> VmResult<Vec<Value>> {
186 VmResult::Ok(vm_try!(Vec::try_from(self)))
187 }
188
189 #[inline]
190 fn count(&self) -> usize {
191 self.len()
192 }
193}