mini_v8/
conversion.rs

1use crate::*;
2use std::collections::{BTreeMap, HashMap, BTreeSet, HashSet};
3use std::hash::{BuildHasher, Hash};
4use std::string::String as StdString;
5use std::time::Duration;
6
7impl ToValue for Value {
8    fn to_value(self, _mv8: &MiniV8) -> Result<Value> {
9        Ok(self)
10    }
11}
12
13impl FromValue for Value {
14    fn from_value(value: Value, _mv8: &MiniV8) -> Result<Self> {
15        Ok(value)
16    }
17}
18
19impl ToValue for () {
20    fn to_value(self, _mv8: &MiniV8) -> Result<Value> {
21        Ok(Value::Undefined)
22    }
23}
24
25impl FromValue for () {
26    fn from_value(_value: Value, _mv8: &MiniV8) -> Result<Self> {
27        Ok(())
28    }
29}
30
31impl<T: ToValue> ToValue for Option<T> {
32    fn to_value(self, mv8: &MiniV8) -> Result<Value> {
33        match self {
34            Some(val) => val.to_value(mv8),
35            None => Ok(Value::Null),
36        }
37    }
38}
39
40impl<T: FromValue> FromValue for Option<T> {
41    fn from_value(value: Value, mv8: &MiniV8) -> Result<Self> {
42        match value {
43            Value::Null | Value::Undefined => Ok(None),
44            value => Ok(Some(T::from_value(value, mv8)?)),
45        }
46    }
47}
48
49impl ToValue for String {
50    fn to_value(self, _mv8: &MiniV8) -> Result<Value> {
51        Ok(Value::String(self))
52    }
53}
54
55impl FromValue for String {
56    fn from_value(value: Value, mv8: &MiniV8) -> Result<String> {
57        value.coerce_string(mv8)
58    }
59}
60
61impl ToValue for Array {
62    fn to_value(self, _mv8: &MiniV8) -> Result<Value> {
63        Ok(Value::Array(self))
64    }
65}
66
67impl FromValue for Array {
68    fn from_value(value: Value, _mv8: &MiniV8) -> Result<Array> {
69        match value {
70            Value::Array(a) => Ok(a),
71            value => Err(Error::from_js_conversion(value.type_name(), "Array")),
72        }
73    }
74}
75
76impl ToValue for Function {
77    fn to_value(self, _mv8: &MiniV8) -> Result<Value> {
78        Ok(Value::Function(self))
79    }
80}
81
82impl FromValue for Function {
83    fn from_value(value: Value, _mv8: &MiniV8) -> Result<Function> {
84        match value {
85            Value::Function(f) => Ok(f),
86            value => Err(Error::from_js_conversion(value.type_name(), "Function")),
87        }
88    }
89}
90
91impl ToValue for Object {
92    fn to_value(self, _mv8: &MiniV8) -> Result<Value> {
93        Ok(Value::Object(self))
94    }
95}
96
97impl FromValue for Object {
98    fn from_value(value: Value, _mv8: &MiniV8) -> Result<Object> {
99        match value {
100            Value::Object(o) => Ok(o),
101            value => Err(Error::from_js_conversion(value.type_name(), "Object")),
102        }
103    }
104}
105
106impl<K, V, S> ToValue for HashMap<K, V, S>
107where
108    K: Eq + Hash + ToValue,
109    V: ToValue,
110    S: BuildHasher,
111{
112    fn to_value(self, mv8: &MiniV8) -> Result<Value> {
113        let object = mv8.create_object();
114        for (k, v) in self.into_iter() {
115            object.set(k, v)?;
116        }
117        Ok(Value::Object(object))
118    }
119}
120
121impl<K, V, S> FromValue for HashMap<K, V, S>
122where
123    K: Eq + Hash + FromValue,
124    V: FromValue,
125    S: BuildHasher + Default,
126{
127    fn from_value(value: Value, _mv8: &MiniV8) -> Result<Self> {
128        match value {
129            Value::Object(o) => o.properties(false)?.collect(),
130            value => Err(Error::from_js_conversion(value.type_name(), "HashMap")),
131        }
132    }
133}
134
135impl<K, V> ToValue for BTreeMap<K, V>
136where
137    K: Ord + ToValue,
138    V: ToValue,
139{
140    fn to_value(self, mv8: &MiniV8) -> Result<Value> {
141        let object = mv8.create_object();
142        for (k, v) in self.into_iter() {
143            object.set(k, v)?;
144        }
145        Ok(Value::Object(object))
146    }
147}
148
149impl<K, V> FromValue for BTreeMap<K, V>
150where
151    K: Ord + FromValue,
152    V: FromValue,
153{
154    fn from_value(value: Value, _mv8: &MiniV8) -> Result<Self> {
155        match value {
156            Value::Object(o) => o.properties(false)?.collect(),
157            value => Err(Error::from_js_conversion(value.type_name(), "BTreeMap")),
158        }
159    }
160}
161
162impl<V: ToValue> ToValue for BTreeSet<V> {
163    fn to_value(self, mv8: &MiniV8) -> Result<Value> {
164        let array = mv8.create_array();
165        for v in self.into_iter() {
166            array.push(v)?;
167        }
168        Ok(Value::Array(array))
169    }
170}
171
172impl<V: FromValue + Ord> FromValue for BTreeSet<V> {
173    fn from_value(value: Value, _mv8: &MiniV8) -> Result<Self> {
174        match value {
175            Value::Array(a) => a.elements().collect(),
176            value => Err(Error::from_js_conversion(value.type_name(), "BTreeSet")),
177        }
178    }
179}
180
181impl<V: ToValue> ToValue for HashSet<V> {
182    fn to_value(self, mv8: &MiniV8) -> Result<Value> {
183        let array = mv8.create_array();
184        for v in self.into_iter() {
185            array.push(v)?;
186        }
187        Ok(Value::Array(array))
188    }
189}
190
191impl<V: FromValue + Hash + Eq> FromValue for HashSet<V> {
192    fn from_value(value: Value, _mv8: &MiniV8) -> Result<Self> {
193        match value {
194            Value::Array(a) => a.elements().collect(),
195            value => Err(Error::from_js_conversion(value.type_name(), "HashSet")),
196        }
197    }
198}
199
200impl<V: ToValue> ToValue for Vec<V> {
201    fn to_value(self, mv8: &MiniV8) -> Result<Value> {
202        let array = mv8.create_array();
203        for v in self.into_iter() {
204            array.push(v)?;
205        }
206        Ok(Value::Array(array))
207    }
208}
209
210impl<V: FromValue> FromValue for Vec<V> {
211    fn from_value(value: Value, _mv8: &MiniV8) -> Result<Self> {
212        match value {
213            Value::Array(a) => a.elements().collect(),
214            value => Err(Error::from_js_conversion(value.type_name(), "Vec")),
215        }
216    }
217}
218
219impl ToValue for bool {
220    fn to_value(self, _mv8: &MiniV8) -> Result<Value> {
221        Ok(Value::Boolean(self))
222    }
223}
224
225impl FromValue for bool {
226    fn from_value(value: Value, mv8: &MiniV8) -> Result<Self> {
227        Ok(value.coerce_boolean(mv8))
228    }
229}
230
231impl ToValue for StdString {
232    fn to_value(self, mv8: &MiniV8) -> Result<Value> {
233        Ok(Value::String(mv8.create_string(&self)))
234    }
235}
236
237impl FromValue for StdString {
238    fn from_value(value: Value, mv8: &MiniV8) -> Result<Self> {
239        Ok(value.coerce_string(mv8)?.to_string())
240    }
241}
242
243impl<'a> ToValue for &'a str {
244    fn to_value(self, mv8: &MiniV8) -> Result<Value> {
245        Ok(Value::String(mv8.create_string(self)))
246    }
247}
248
249macro_rules! convert_number {
250    ($prim_ty: ty) => {
251        impl ToValue for $prim_ty {
252            fn to_value(self, _mv8: &MiniV8) -> Result<Value> {
253                Ok(Value::Number(self as f64))
254            }
255        }
256
257        impl FromValue for $prim_ty {
258            fn from_value(value: Value, mv8: &MiniV8) -> Result<Self> {
259                Ok(value.coerce_number(mv8)? as $prim_ty)
260            }
261        }
262    }
263}
264
265convert_number!(i8);
266convert_number!(u8);
267convert_number!(i16);
268convert_number!(u16);
269convert_number!(i32);
270convert_number!(u32);
271convert_number!(i64);
272convert_number!(u64);
273convert_number!(isize);
274convert_number!(usize);
275convert_number!(f32);
276convert_number!(f64);
277
278impl ToValue for Duration {
279    fn to_value(self, _mv8: &MiniV8) -> Result<Value> {
280        Ok(Value::Date((self.as_secs() as f64) + (self.as_nanos() as f64) / 1_000_000_000.0))
281    }
282}
283
284impl FromValue for Duration {
285    fn from_value(value: Value, _mv8: &MiniV8) -> Result<Duration> {
286        match value {
287            Value::Date(timestamp) => {
288                let secs = timestamp / 1000.0;
289                let nanos = ((secs - secs.floor()) * 1_000_000.0).round() as u32;
290                Ok(Duration::new(secs as u64, nanos))
291            },
292            value => Err(Error::from_js_conversion(value.type_name(), "Duration")),
293        }
294    }
295}
296
297impl ToValues for Values {
298    fn to_values(self, _mv8: &MiniV8) -> Result<Values> {
299        Ok(self)
300    }
301}
302
303impl FromValues for Values {
304    fn from_values(values: Values, _mv8: &MiniV8) -> Result<Self> {
305        Ok(values)
306    }
307}
308
309impl<T: ToValue> ToValues for Variadic<T> {
310    fn to_values(self, mv8: &MiniV8) -> Result<Values> {
311        self.0.into_iter().map(|value| value.to_value(mv8)).collect()
312    }
313}
314
315impl<T: FromValue> FromValues for Variadic<T> {
316    fn from_values(values: Values, mv8: &MiniV8) -> Result<Self> {
317        values.into_iter()
318            .map(|value| T::from_value(value, mv8))
319            .collect::<Result<Vec<T>>>()
320            .map(Variadic)
321    }
322}
323
324impl ToValues for () {
325    fn to_values(self, _mv8: &MiniV8) -> Result<Values> {
326        Ok(Values::new())
327    }
328}
329
330impl FromValues for () {
331    fn from_values(_values: Values, _mv8: &MiniV8) -> Result<Self> {
332        Ok(())
333    }
334}
335
336macro_rules! impl_tuple {
337    ($($name:ident),*) => (
338        impl<$($name),*> ToValues for ($($name,)*)
339        where
340            $($name: ToValue,)*
341        {
342            #[allow(non_snake_case)]
343            fn to_values(self, mv8: &MiniV8) -> Result<Values> {
344                let ($($name,)*) = self;
345                let reservation = $({ let _ = &$name; 1 } +)* 0;
346                let mut results = Vec::with_capacity(reservation);
347                $(results.push($name.to_value(mv8)?);)*
348                Ok(Values::from_vec(results))
349            }
350        }
351
352        impl<$($name),*> FromValues for ($($name,)*)
353        where
354            $($name: FromValue,)*
355        {
356            #[allow(non_snake_case, unused_mut, unused_variables)]
357            fn from_values(values: Values, mv8: &MiniV8) -> Result<Self> {
358                let mut iter = values.into_vec().into_iter();
359                Ok(($({
360                    let $name = ();
361                    FromValue::from_value(iter.next().unwrap_or(Value::Undefined), mv8)?
362                },)*))
363            }
364        }
365
366        impl<$($name,)* VAR> ToValues for ($($name,)* Variadic<VAR>)
367        where
368            $($name: ToValue,)*
369            VAR: ToValue,
370        {
371            #[allow(non_snake_case)]
372            fn to_values(self, mv8: &MiniV8) -> Result<Values> {
373                let ($($name,)* variadic) = self;
374                let reservation = $({ let _ = &$name; 1 } +)* 1;
375                let mut results = Vec::with_capacity(reservation);
376                $(results.push($name.to_value(mv8)?);)*
377                if results.is_empty() {
378                    Ok(variadic.to_values(mv8)?)
379                } else {
380                    results.append(&mut variadic.to_values(mv8)?.into_vec());
381                    Ok(Values::from_vec(results))
382                }
383            }
384        }
385
386        impl<$($name,)* VAR> FromValues for ($($name,)* Variadic<VAR>)
387        where
388            $($name: FromValue,)*
389            VAR: FromValue,
390        {
391            #[allow(non_snake_case, unused_mut, unused_variables)]
392            fn from_values(values: Values, mv8: &MiniV8) -> Result<Self> {
393                let mut values = values.into_vec();
394                let len = values.len();
395                let split = $({ let $name = (); 1 } +)* 0;
396
397                if len < split {
398                    values.reserve(split - len);
399                    for _ in len..split {
400                        values.push(Value::Undefined);
401                    }
402                }
403
404                let last_values = Values::from_vec(values.split_off(split));
405                let variadic = FromValues::from_values(last_values, mv8)?;
406
407                let mut iter = values.into_iter();
408                let ($($name,)*) = ($({ let $name = (); iter.next().unwrap() },)*);
409
410                Ok(($(FromValue::from_value($name, mv8)?,)* variadic))
411            }
412        }
413    )
414}
415
416impl_tuple!(A);
417impl_tuple!(A, B);
418impl_tuple!(A, B, C);
419impl_tuple!(A, B, C, D);
420impl_tuple!(A, B, C, D, E);
421impl_tuple!(A, B, C, D, E, F);
422impl_tuple!(A, B, C, D, E, F, G);
423impl_tuple!(A, B, C, D, E, F, G, H);
424impl_tuple!(A, B, C, D, E, F, G, H, I);
425impl_tuple!(A, B, C, D, E, F, G, H, I, J);
426impl_tuple!(A, B, C, D, E, F, G, H, I, J, K);
427impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
428impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
429impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
430impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
431impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);