1use crate::{Any, AnyObj, Panic, Shared, Value, VmError, VmErrorKind};
2
3pub trait ToValue: Sized {
5 fn to_value(self) -> Result<Value, VmError>;
7}
8
9pub trait UnsafeToValue: Sized {
11 type Guard: 'static;
13
14 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
49impl<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
66impl ToValue for Box<str> {
69 fn to_value(self) -> Result<Value, VmError> {
70 Ok(Value::from(Shared::new(self.to_string())))
71 }
72}
73
74impl<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
119macro_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
158macro_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>);