runestick/
to_value.rs

1use crate::{Any, AnyObj, Panic, Shared, Value, VmError, VmErrorKind};
2
3/// Trait for converting types into values.
4pub trait ToValue: Sized {
5    /// Convert into a value.
6    fn to_value(self) -> Result<Value, VmError>;
7}
8
9/// Trait for converting types into values.
10pub trait UnsafeToValue: Sized {
11    /// The type used to guard the unsafe value conversion.
12    type Guard: 'static;
13
14    /// Convert into a value.
15    ///
16    /// # Safety
17    ///
18    /// The value returned must not be used after the guard associated with it
19    /// has been dropped.
20    unsafe fn unsafe_to_value(self) -> Result<(Value, Self::Guard), VmError>;
21}
22
23impl<T> ToValue for T
24where
25    T: Any,
26{
27    fn to_value(self) -> Result<Value, VmError> {
28        Ok(Value::from(AnyObj::new(self)))
29    }
30}
31
32impl<T> UnsafeToValue for T
33where
34    T: ToValue,
35{
36    type Guard = ();
37
38    unsafe fn unsafe_to_value(self) -> Result<(Value, Self::Guard), VmError> {
39        Ok((self.to_value()?, ()))
40    }
41}
42
43impl ToValue for &Value {
44    fn to_value(self) -> Result<Value, VmError> {
45        Ok(self.clone())
46    }
47}
48
49// Option impls
50
51impl<T> ToValue for Option<T>
52where
53    T: ToValue,
54{
55    fn to_value(self) -> Result<Value, VmError> {
56        Ok(Value::from(Shared::new(match self {
57            Some(some) => {
58                let value = some.to_value()?;
59                Some(value)
60            }
61            None => None,
62        })))
63    }
64}
65
66// String impls
67
68impl ToValue for Box<str> {
69    fn to_value(self) -> Result<Value, VmError> {
70        Ok(Value::from(Shared::new(self.to_string())))
71    }
72}
73
74// Result impls
75
76impl<T> ToValue for Result<T, Panic>
77where
78    T: ToValue,
79{
80    fn to_value(self) -> Result<Value, VmError> {
81        match self {
82            Ok(value) => Ok(value.to_value()?),
83            Err(reason) => Err(VmError::from(VmErrorKind::Panic { reason })),
84        }
85    }
86}
87
88impl<T> ToValue for Result<T, VmError>
89where
90    T: ToValue,
91{
92    fn to_value(self) -> Result<Value, VmError> {
93        match self {
94            Ok(value) => Ok(value.to_value()?),
95            Err(error) => Err(error),
96        }
97    }
98}
99
100impl<T, E> ToValue for Result<T, E>
101where
102    T: ToValue,
103    E: ToValue,
104{
105    fn to_value(self) -> Result<Value, VmError> {
106        Ok(match self {
107            Ok(ok) => {
108                let ok = ok.to_value()?;
109                Value::from(Shared::new(Ok(ok)))
110            }
111            Err(err) => {
112                let err = err.to_value()?;
113                Value::from(Shared::new(Err(err)))
114            }
115        })
116    }
117}
118
119// number impls
120
121macro_rules! number_value_trait {
122    ($ty:ty) => {
123        impl ToValue for $ty {
124            fn to_value(self) -> Result<Value, $crate::VmError> {
125                use std::convert::TryInto as _;
126
127                match self.try_into() {
128                    Ok(number) => Ok(Value::Integer(number)),
129                    Err(..) => Err($crate::VmError::from(
130                        $crate::VmErrorKind::IntegerToValueCoercionError {
131                            from: $crate::VmIntegerRepr::from(self),
132                            to: std::any::type_name::<i64>(),
133                        },
134                    )),
135                }
136            }
137        }
138    };
139}
140
141number_value_trait!(u16);
142number_value_trait!(u32);
143number_value_trait!(u64);
144number_value_trait!(u128);
145number_value_trait!(usize);
146number_value_trait!(i8);
147number_value_trait!(i16);
148number_value_trait!(i32);
149number_value_trait!(i128);
150number_value_trait!(isize);
151
152impl ToValue for f32 {
153    fn to_value(self) -> Result<Value, VmError> {
154        Ok(Value::Float(self as f64))
155    }
156}
157
158// map impls
159
160macro_rules! impl_map {
161    ($ty:ty) => {
162        impl<T> $crate::ToValue for $ty
163        where
164            T: $crate::ToValue,
165        {
166            fn to_value(self) -> Result<$crate::Value, $crate::VmError> {
167                let mut output = crate::Object::with_capacity(self.len());
168
169                for (key, value) in self {
170                    output.insert(key, value.to_value()?);
171                }
172
173                Ok($crate::Value::from($crate::Shared::new(output)))
174            }
175        }
176    };
177}
178
179impl_map!(std::collections::HashMap<String, T>);