1use super::*;
2use serde::de::*;
3
4
5impl<'de, T: Deserialize<'de>> ReadJs for T {
6 fn read_js(ctx: &DukContext, obj_index: i32) -> Result<Self, JsError> {
7 Self::deserialize(JsEngineDeserializer::new(ctx, obj_index))
8 }
9}
10
11pub struct JsEngineDeserializer<'a> {
12 ctx: &'a DukContext,
13 index: i32,
14 len: usize,
15}
16
17impl <'a> JsEngineDeserializer<'a> {
18 pub fn new(ctx: &'a DukContext, index: i32) -> Self {
19 Self { ctx, index, len: 0 }
20 }
21}
22
23impl<'de, 'a> Deserializer<'de> for JsEngineDeserializer<'a> {
24 type Error = JsError;
25
26 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
27 use super::DukType::*;
28
29 match self.ctx.get_type(self.index) {
30 DUK_TYPE_UNDEFINED | DUK_TYPE_NULL => visitor.visit_none(),
31 DUK_TYPE_BOOLEAN => visitor.visit_bool(self.ctx.get_boolean(self.index)),
32 DUK_TYPE_NUMBER => {
33 let n = self.ctx.get_number(self.index);
34 if n.is_finite() && (n.trunc() - n).abs() < f64::EPSILON {
35 visitor.visit_i64(n as i64)
36 } else {
37 visitor.visit_f64(n)
38 }
39 }
40 DUK_TYPE_STRING => visitor.visit_str(&self.ctx.get_string(self.index)),
41 DUK_TYPE_BUFFER => visitor.visit_bytes(self.ctx.get_buffer(self.index)),
42 DUK_TYPE_OBJECT => {
43 if self.ctx.is_array(self.index) {
44 let len = self.ctx.get_length( self.index);
45 self.ctx.enum_indices(self.index);
46 let res = visitor.visit_seq(JsEngineDeserializer { ctx: self.ctx, index: -1, len });
47 self.ctx.pop();
48 res
49 } else if self.ctx.is_pure_object(self.index) {
50 self.ctx.enum_keys(self.index);
51 let res = visitor.visit_map(JsEngineDeserializer { ctx: self.ctx, index: -1, len: 0 });
52 self.ctx.pop();
53 res
54 } else {
55 return Err(JsError::from(format!("Unimplemented javascript object type"))); }
57 }
58 _ => return Err(JsError::from(format!("Unimplemented javascript object type"))) }
60 }
61
62 fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
63 self.deserialize_any(visitor)
64 }
65
66 fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
67 self.deserialize_any(visitor)
68 }
69
70 fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
71 self.deserialize_any(visitor)
72 }
73
74 fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
75 self.deserialize_any(visitor)
76 }
77
78 fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
79 self.deserialize_any(visitor)
80 }
81
82 fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
83 self.deserialize_any(visitor)
84 }
85
86 fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
87 self.deserialize_any(visitor)
88 }
89
90 fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
91 self.deserialize_any(visitor)
92 }
93
94 fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
95 self.deserialize_any(visitor)
96 }
97
98 fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
99 self.deserialize_any(visitor)
100 }
101
102 fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
103 self.deserialize_any(visitor)
104 }
105
106 fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
107 self.deserialize_any(visitor)
108 }
109
110 fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
111 self.deserialize_any(visitor)
112 }
113
114 fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
115 self.deserialize_any(visitor)
116 }
117
118 fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
119 self.deserialize_any(visitor)
120 }
121
122 fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
123 self.deserialize_any(visitor)
124 }
125
126 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
127 use super::DukType::{DUK_TYPE_NULL, DUK_TYPE_UNDEFINED};
128
129 match self.ctx.get_type(self.index) {
130 DUK_TYPE_UNDEFINED | DUK_TYPE_NULL => visitor.visit_none(),
131 _ => visitor.visit_some(self)
132 }
133 }
134
135 fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
136 visitor.visit_unit()
137 }
138
139 fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
140 self.deserialize_any(visitor)
141 }
142
143 fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
144 self.deserialize_any(visitor)
145 }
146
147 fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
148 self.deserialize_any(visitor)
149 }
150
151 fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
152 self.deserialize_any(visitor)
153 }
154
155 fn deserialize_tuple_struct<V>(self, _name: &'static str, _len: usize, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
156 self.deserialize_any(visitor)
157 }
158
159 fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
160 self.deserialize_any(visitor)
161 }
162
163 fn deserialize_struct<V>(self, _name: &'static str, _fields: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
164 self.deserialize_any(visitor)
165 }
166
167 fn deserialize_enum<V>(self, _name: &'static str, _variants: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
168 use super::DukType::*;
169
170 match self.ctx.get_type(self.index) {
171 DUK_TYPE_STRING => {
173 visitor.visit_enum(self.ctx.get_string(self.index).into_deserializer())
174 }
175 DUK_TYPE_OBJECT if self.ctx.is_pure_object(self.index) => {
177 self.ctx.enum_keys(self.index);
178 if !self.ctx.next(-1) {
179 self.ctx.pop();
180 return Err(JsError::from(String::from(
181 "expected an enum object with a single variant key, got an empty object",
182 )));
183 }
184 if self.ctx.next(-3) {
186 self.ctx.pop_n(2); self.ctx.pop_n(2); self.ctx.pop(); return Err(JsError::from(String::from(
191 "expected an enum object with a single variant key, got multiple keys",
192 )));
193 }
194 let res = visitor.visit_enum(JsEnumAccess { ctx: self.ctx });
195 self.ctx.pop_n(2); self.ctx.pop(); res
198 }
199 _ => Err(JsError::from(String::from(
200 "expected a string or an object to deserialize an enum",
201 ))),
202 }
203 }
204
205 fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
206 self.deserialize_any(visitor)
207 }
208
209 fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
210 self.deserialize_any(visitor)
211 }
212}
213
214struct JsEnumAccess<'a> {
217 ctx: &'a DukContext,
218}
219
220impl<'de, 'a> EnumAccess<'de> for JsEnumAccess<'a> {
221 type Error = JsError;
222 type Variant = Self;
223
224 fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
225 where V: DeserializeSeed<'de>
226 {
227 let variant = seed.deserialize(JsEngineDeserializer { ctx: self.ctx, index: -2, len: 0 })?;
229 Ok((variant, self))
230 }
231}
232
233impl<'de, 'a> VariantAccess<'de> for JsEnumAccess<'a> {
234 type Error = JsError;
235
236 fn unit_variant(self) -> Result<(), Self::Error> {
237 Ok(())
238 }
239
240 fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
241 where T: DeserializeSeed<'de>
242 {
243 seed.deserialize(JsEngineDeserializer { ctx: self.ctx, index: -1, len: 0 })
245 }
246
247 fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
248 where V: Visitor<'de>
249 {
250 JsEngineDeserializer { ctx: self.ctx, index: -1, len: 0 }.deserialize_seq(visitor)
251 }
252
253 fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V)
254 -> Result<V::Value, Self::Error> where V: Visitor<'de>
255 {
256 JsEngineDeserializer { ctx: self.ctx, index: -1, len: 0 }.deserialize_map(visitor)
257 }
258}
259
260impl<'de, 'a> MapAccess<'de> for JsEngineDeserializer<'a> {
261 type Error = JsError;
262
263 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> where K: DeserializeSeed<'de> {
264 if self.ctx.next(-1) {
265 Ok(Some(seed.deserialize(JsEngineDeserializer { ctx: self.ctx, index: -2, len: 0 })?))
266 } else {
267 Ok(None)
268 }
269 }
270
271 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error> where V: DeserializeSeed<'de> {
272 let res = seed.deserialize(JsEngineDeserializer { ctx: self.ctx, index: -1, len: 0 });
273 self.ctx.pop_n(2);
274 res
275 }
276
277 fn next_entry_seed<K, V>(&mut self, kseed: K, vseed: V) -> Result<Option<(K::Value, V::Value)>, Self::Error> where K: DeserializeSeed<'de>, V: DeserializeSeed<'de> {
278 if self.ctx.next(-1) {
279 let k = kseed.deserialize(JsEngineDeserializer { ctx: self.ctx, index: -2, len: 0 })?;
280 let v = vseed.deserialize(JsEngineDeserializer { ctx: self.ctx, index: -1, len: 0 })?;
281 self.ctx.pop_n(2);
282 Ok(Some((k, v)))
283 } else {
284 Ok(None)
285 }
286 }
287}
288
289impl<'de, 'a> SeqAccess<'de> for JsEngineDeserializer<'a> {
290 type Error = JsError;
291
292 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> where T: DeserializeSeed<'de> {
293 if self.ctx.next(-1) {
294 let v = seed.deserialize(JsEngineDeserializer { ctx: self.ctx, index: -1, len: 0 })?;
295 self.ctx.pop_n(2);
296 Ok(Some(v))
297 } else {
298 Ok(None)
299 }
300 }
301
302 fn size_hint(&self) -> Option<usize> {
303 Some(self.len)
304 }
305}
306
307
308#[cfg(test)]
309mod tests {
310 use super::*;
311 use smart_default::SmartDefault;
312 use serde::{Serialize, Deserialize};
313
314 fn deserialize<'a, T: std::fmt::Debug + Serialize + Deserialize<'a> + Default>(value: &T) {
315 let e = JsEngine::new().unwrap();
316 e.write(value).unwrap_or_else(|err| {
317 panic!("{}", err);
318 });
319 e.put_global_string("value");
320 e.get_global_string("value");
321 let val: T = e.read_top().unwrap_or_else(|err| {
322 panic!("{}", err);
323 });
324 assert_eq!(format!("{:?}", value), format!("{:?}", val));
325 }
326
327 fn deserialize_expr<'a, T: std::fmt::Debug + Deserialize<'a>>(expr: &str) -> T {
328 let e = JsEngine::new().unwrap();
329 e.eval(expr).unwrap();
330 e.get_global_string("value");
331 let val: T = e.read_top().unwrap_or_else(|err| {
332 panic!("{}", err);
333 });
334 val
335 }
336
337 fn test_deserialize<'a, T: std::fmt::Debug + Serialize + Deserialize<'a> + Default>(value: &T) {
338 deserialize(value);
339 }
340
341 #[derive(Debug, SmartDefault, Serialize, Deserialize)]
342 struct TestStruct {
343 #[default = "string value"]
344 string_field: String,
345 #[default = 'A']
346 char_field: char,
347 #[default = 1]
348 i8_field: i8,
349 #[default(_code = "vec![1.0,2.0,3.0,7.5]")]
350 arr_field: Vec<f64>,
351 optional1: Option<f64>,
352 optional2: Option<f64>,
353 unit: ()
354 }
355
356 #[test]
357 fn read_struct() {
358 let mut p = TestStruct::default();
359 p.char_field = 'B';
360 p.i8_field = 44;
361 p.optional1 = Some(3.14);
362 test_deserialize(&p);
363 }
364
365 #[test]
366 fn deserialize_zero() {
367 #[derive(Debug, Deserialize)]
368 struct TestStruct {
369 float_field: f64,
370 int_field: i64,
371 }
372
373 let val: TestStruct = deserialize_expr(r#"
375 value = {
376 float_field: 0,
377 int_field: 0
378 };
379"#);
380 assert_eq!(val.float_field, 0.0);
381 assert_eq!(val.int_field, 0);
382 }
383
384 #[test]
385 fn deserialize_nan() {
386 #[derive(Debug, Deserialize)]
387 struct TestStruct {
388 float_field: f64,
389 }
390
391 let val: TestStruct = deserialize_expr(r#"
393 value = {
394 float_field: NaN
395 };
396"#);
397 assert!(val.float_field.is_nan());
398 }
399
400 #[test]
401 fn deserialize_unit() {
402 let _val: () = deserialize_expr(r#"
404 value = {
405 test: "asfads"
406 };
407"#);
408 }
409
410 #[derive(Debug, PartialEq, Serialize, Deserialize)]
411 #[serde(rename_all = "lowercase")]
412 enum HttpMethod { Get, Post, Delete }
413
414 #[derive(Debug, PartialEq, Serialize, Deserialize)]
415 enum Shape {
416 Empty,
417 Radius(f64),
418 Pair(i64, i64),
419 Rect { w: i64, h: i64 },
420 }
421
422 #[derive(Debug, PartialEq, Serialize, Deserialize)]
423 struct Req { url: String, method: HttpMethod }
424
425 #[test]
426 fn bare_unit_variant_from_string() {
427 let val: HttpMethod = deserialize_expr("value = 'post'");
428 assert_eq!(val, HttpMethod::Post);
429 let val: HttpMethod = deserialize_expr("value = 'get'");
430 assert_eq!(val, HttpMethod::Get);
431 }
432
433 #[test]
434 fn unit_variant_as_struct_field() {
435 let val: Req = deserialize_expr(r#"
437 value = {
438 url: 'http://x',
439 method: 'delete'
440 };
441"#);
442 assert_eq!(val, Req { url: "http://x".to_string(), method: HttpMethod::Delete });
443 }
444
445 #[test]
446 fn unknown_variant_is_a_clean_error() {
447 let e = JsEngine::new().unwrap();
448 e.eval("value = 'teapot'").unwrap();
449 e.get_global_string("value");
450 let res: Result<HttpMethod, _> = e.read_top();
451 let err = res.unwrap_err();
452 assert!(err.to_string().contains("unknown variant"), "error was: {}", err);
453 }
454
455 #[test]
456 fn tagged_variants_from_js_objects() {
457 let val: Shape = deserialize_expr("value = ({Radius: 2.5})");
458 assert_eq!(val, Shape::Radius(2.5));
459
460 let val: Shape = deserialize_expr("value = ({Pair: [1,2]})");
461 assert_eq!(val, Shape::Pair(1, 2));
462
463 let val: Shape = deserialize_expr("value = ({Rect: {w:3,h:4}})");
464 assert_eq!(val, Shape::Rect { w: 3, h: 4 });
465 }
466
467 #[test]
468 fn empty_object_variant_is_a_clean_error() {
469 let e = JsEngine::new().unwrap();
470 e.eval("value = ({})").unwrap();
471 e.get_global_string("value");
472 let res: Result<Shape, _> = e.read_top();
473 let err = res.unwrap_err();
474 assert!(err.to_string().contains("empty object"), "error was: {}", err);
475 }
476
477 #[test]
478 fn multi_key_object_variant_is_a_clean_error() {
479 let e = JsEngine::new().unwrap();
480 e.eval("value = ({Radius: 2.5, Extra: 999})").unwrap();
481 e.get_global_string("value");
482 let res: Result<Shape, _> = e.read_top();
483 let err = res.unwrap_err();
484 assert!(err.to_string().contains("multiple keys"), "error was: {}", err);
485 }
486
487 #[test]
488 fn all_variant_shapes_round_trip() {
489 for shape in [
490 Shape::Empty,
491 Shape::Radius(2.5),
492 Shape::Pair(1, 2),
493 Shape::Rect { w: 3, h: 4 },
494 ] {
495 let e = JsEngine::new().unwrap();
496 e.write(&shape).unwrap();
497 e.put_global_string("value");
498 e.get_global_string("value");
499 let val: Shape = e.read_top().unwrap();
500 assert_eq!(shape, val);
501 }
502
503 let req = Req { url: "http://x".to_string(), method: HttpMethod::Post };
504 let e = JsEngine::new().unwrap();
505 e.write(&req).unwrap();
506 e.put_global_string("value");
507 e.get_global_string("value");
508 let val: Req = e.read_top().unwrap();
509 assert_eq!(req, val);
510 }
511}