rune/runtime/
vec_tuple.rs

1use crate::alloc::Vec;
2use crate::runtime::{FromValue, RuntimeError, ToValue, Value, VmErrorKind};
3
4/// A helper type to deserialize arrays with different interior types.
5///
6/// This implements [FromValue], allowing it to be used as a return value from
7/// a virtual machine.
8///
9/// [FromValue]: crate::FromValue
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct VecTuple<T>(pub T);
12
13impl<T> VecTuple<T>
14where
15    Self: ToValue,
16{
17    /// Construct a new vector tuple for serializing values.
18    pub fn new(inner: T) -> Self {
19        Self(inner)
20    }
21}
22
23macro_rules! impl_from_value_tuple_vec {
24    ($count:expr $(, $ty:ident $var:ident $_:expr)*) => {
25        impl<$($ty,)*> FromValue for VecTuple<($($ty,)*)>
26        where
27            $($ty: FromValue,)*
28        {
29            fn from_value(value: Value) -> Result<Self, RuntimeError> {
30                let vec = value.into_ref::<$crate::runtime::Vec>()?;
31
32                let [$($var,)*] = vec.as_slice() else {
33                    return Err(RuntimeError::new(VmErrorKind::ExpectedTupleLength {
34                        actual: vec.len(),
35                        expected: $count,
36                    }));
37                };
38
39                Ok(VecTuple(($(<$ty>::from_value($var.clone())?,)*)))
40            }
41        }
42
43        impl<$($ty,)*> ToValue for VecTuple<($($ty,)*)>
44        where
45            $($ty: ToValue,)*
46        {
47            #[allow(unused_mut)]
48            fn to_value(self) -> Result<Value, RuntimeError> {
49                let ($($var,)*) = self.0;
50                let mut vec = Vec::try_with_capacity($count)?;
51
52                $(
53                    let $var = $var.to_value()?;
54                    vec.try_push($var)?;
55                )*
56
57                Ok(Value::vec(vec)?)
58            }
59        }
60    };
61}
62
63repeat_macro!(impl_from_value_tuple_vec);