use super::*;
use serde::de::*;
impl<'de, T: Deserialize<'de>> ReadJs for T {
fn read_js(ctx: &DukContext, obj_index: i32) -> Result<Self, JsError> {
Self::deserialize(JsEngineDeserializer::new(ctx, obj_index))
}
}
pub struct JsEngineDeserializer<'a> {
ctx: &'a DukContext,
index: i32,
len: usize,
}
impl <'a> JsEngineDeserializer<'a> {
pub fn new(ctx: &'a DukContext, index: i32) -> Self {
Self { ctx, index, len: 0 }
}
}
impl<'de, 'a> Deserializer<'de> for JsEngineDeserializer<'a> {
type Error = JsError;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
use super::DukType::*;
match self.ctx.get_type(self.index) {
DUK_TYPE_UNDEFINED | DUK_TYPE_NULL => visitor.visit_none(),
DUK_TYPE_BOOLEAN => visitor.visit_bool(self.ctx.get_boolean(self.index)),
DUK_TYPE_NUMBER => {
let n = self.ctx.get_number(self.index);
if n.is_finite() && (n.trunc() - n).abs() < f64::EPSILON {
visitor.visit_i64(n as i64)
} else {
visitor.visit_f64(n)
}
}
DUK_TYPE_STRING => visitor.visit_str(self.ctx.get_string(self.index)),
DUK_TYPE_BUFFER => visitor.visit_bytes(self.ctx.get_buffer(self.index)),
DUK_TYPE_OBJECT => {
if self.ctx.is_array(self.index) {
let len = self.ctx.get_length( self.index);
self.ctx.enum_indices(self.index);
let res = visitor.visit_seq(JsEngineDeserializer { ctx: self.ctx, index: -1, len });
self.ctx.pop();
res
} else if self.ctx.is_pure_object(self.index) {
self.ctx.enum_keys(self.index);
let res = visitor.visit_map(JsEngineDeserializer { ctx: self.ctx, index: -1, len: 0 });
self.ctx.pop();
res
} else {
return Err(JsError::from(format!("Unimplemented javascript object type"))); }
}
_ => return Err(JsError::from(format!("Unimplemented javascript object type"))) }
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
use super::DukType::{DUK_TYPE_NULL, DUK_TYPE_UNDEFINED};
match self.ctx.get_type(self.index) {
DUK_TYPE_UNDEFINED | DUK_TYPE_NULL => visitor.visit_none(),
_ => visitor.visit_some(self)
}
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
visitor.visit_unit()
}
fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_tuple_struct<V>(self, _name: &'static str, _len: usize, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_struct<V>(self, _name: &'static str, _fields: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_enum<V>(self, _name: &'static str, _variants: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
self.deserialize_any(visitor)
}
}
impl<'de, 'a> MapAccess<'de> for JsEngineDeserializer<'a> {
type Error = JsError;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> where K: DeserializeSeed<'de> {
if self.ctx.next(-1) {
Ok(Some(seed.deserialize(JsEngineDeserializer { ctx: self.ctx, index: -2, len: 0 })?))
} else {
Ok(None)
}
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error> where V: DeserializeSeed<'de> {
let res = seed.deserialize(JsEngineDeserializer { ctx: self.ctx, index: -1, len: 0 });
self.ctx.pop_n(2);
res
}
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> {
if self.ctx.next(-1) {
let k = kseed.deserialize(JsEngineDeserializer { ctx: self.ctx, index: -2, len: 0 })?;
let v = vseed.deserialize(JsEngineDeserializer { ctx: self.ctx, index: -1, len: 0 })?;
self.ctx.pop_n(2);
Ok(Some((k, v)))
} else {
Ok(None)
}
}
}
impl<'de, 'a> SeqAccess<'de> for JsEngineDeserializer<'a> {
type Error = JsError;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> where T: DeserializeSeed<'de> {
if self.ctx.next(-1) {
let v = seed.deserialize(JsEngineDeserializer { ctx: self.ctx, index: -1, len: 0 })?;
self.ctx.pop_n(2);
Ok(Some(v))
} else {
Ok(None)
}
}
fn size_hint(&self) -> Option<usize> {
Some(self.len)
}
}
#[cfg(test)]
mod tests {
use super::*;
use smart_default::SmartDefault;
use serde::{Serialize, Deserialize};
fn deserialize<'a, T: std::fmt::Debug + Serialize + Deserialize<'a> + Default>(value: &T) {
let e = JsEngine::new().unwrap();
e.write(value).unwrap_or_else(|err| {
panic!("{}", err);
});
e.put_global_string("value");
e.get_global_string("value");
let val: T = e.read_top().unwrap_or_else(|err| {
panic!("{}", err);
});
assert_eq!(format!("{:?}", value), format!("{:?}", val));
}
fn deserialize_expr<'a, T: std::fmt::Debug + Deserialize<'a>>(expr: &str) -> T {
let e = JsEngine::new().unwrap();
e.eval(expr).unwrap();
e.get_global_string("value");
let val: T = e.read_top().unwrap_or_else(|err| {
panic!("{}", err);
});
val
}
fn test_deserialize<'a, T: std::fmt::Debug + Serialize + Deserialize<'a> + Default>(value: &T) {
deserialize(value);
}
#[derive(Debug, SmartDefault, Serialize, Deserialize)]
struct TestStruct {
#[default = "string value"]
string_field: String,
#[default = 'A']
char_field: char,
#[default = 1]
i8_field: i8,
#[default(_code = "vec![1.0,2.0,3.0,7.5]")]
arr_field: Vec<f64>,
optional1: Option<f64>,
optional2: Option<f64>,
unit: ()
}
#[test]
fn read_struct() {
let mut p = TestStruct::default();
p.char_field = 'B';
p.i8_field = 44;
p.optional1 = Some(3.14);
test_deserialize(&p);
}
#[test]
fn deserialize_zero() {
#[derive(Debug, Deserialize)]
struct TestStruct {
float_field: f64,
int_field: i64,
}
let val: TestStruct = deserialize_expr(r#"
value = {
float_field: 0,
int_field: 0
};
"#);
assert_eq!(val.float_field, 0.0);
assert_eq!(val.int_field, 0);
}
#[test]
fn deserialize_nan() {
#[derive(Debug, Deserialize)]
struct TestStruct {
float_field: f64,
}
let val: TestStruct = deserialize_expr(r#"
value = {
float_field: NaN
};
"#);
assert!(val.float_field.is_nan());
}
#[test]
fn deserialize_unit() {
let _val: () = deserialize_expr(r#"
value = {
test: "asfads"
};
"#);
}
}