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);