use rusty_v8 as v8; use serde::de::{self, Visitor}; use serde::Deserialize; use std::convert::TryFrom; use crate::error::{Error, Result}; use crate::keys::{v8_struct_key, KeyCache}; use crate::payload::ValueType; use crate::magic; pub struct Deserializer<'a, 'b, 's> { input: v8::Local<'a, v8::Value>, scope: &'b mut v8::HandleScope<'s>, _key_cache: Option<&'b mut KeyCache>, } impl<'a, 'b, 's> Deserializer<'a, 'b, 's> { pub fn new( scope: &'b mut v8::HandleScope<'s>, input: v8::Local<'a, v8::Value>, key_cache: Option<&'b mut KeyCache>, ) -> Self { Deserializer { input, scope, _key_cache: key_cache, } } } // from_v8 deserializes a v8::Value into a Deserializable / rust struct pub fn from_v8<'de, 'a, 'b, 's, T>( scope: &'b mut v8::HandleScope<'s>, input: v8::Local<'a, v8::Value>, ) -> Result where T: Deserialize<'de>, { let mut deserializer = Deserializer::new(scope, input, None); let t = T::deserialize(&mut deserializer)?; Ok(t) } // like from_v8 except accepts a KeyCache to optimize struct key decoding pub fn from_v8_cached<'de, 'a, 'b, 's, T>( scope: &'b mut v8::HandleScope<'s>, input: v8::Local<'a, v8::Value>, key_cache: &mut KeyCache, ) -> Result where T: Deserialize<'de>, { let mut deserializer = Deserializer::new(scope, input, Some(key_cache)); let t = T::deserialize(&mut deserializer)?; Ok(t) } macro_rules! wip { ($method:ident) => { fn $method(self, _v: V) -> Result where V: Visitor<'de>, { unimplemented!() } }; } macro_rules! deserialize_signed { ($dmethod:ident, $vmethod:ident, $t:tt) => { fn $dmethod(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.$vmethod(self.input.integer_value(&mut self.scope).unwrap() as $t) } }; } impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> for &'x mut Deserializer<'a, 'b, 's> { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { match ValueType::from_v8(self.input) { ValueType::Null => self.deserialize_unit(visitor), ValueType::Bool => self.deserialize_bool(visitor), ValueType::Number => self.deserialize_f64(visitor), ValueType::String => self.deserialize_string(visitor), ValueType::Array => self.deserialize_seq(visitor), ValueType::Object => self.deserialize_map(visitor), } } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { if self.input.is_boolean() { visitor.visit_bool(self.input.boolean_value(&mut self.scope)) } else { Err(Error::ExpectedBoolean) } } deserialize_signed!(deserialize_i8, visit_i8, i8); deserialize_signed!(deserialize_i16, visit_i16, i16); deserialize_signed!(deserialize_i32, visit_i32, i32); deserialize_signed!(deserialize_i64, visit_i64, i64); // TODO: maybe handle unsigned by itself ? deserialize_signed!(deserialize_u8, visit_u8, u8); deserialize_signed!(deserialize_u16, visit_u16, u16); deserialize_signed!(deserialize_u32, visit_u32, u32); deserialize_signed!(deserialize_u64, visit_u64, u64); fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_f32(self.input.number_value(&mut self.scope).unwrap() as f32) } fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_f64(self.input.number_value(&mut self.scope).unwrap()) } wip!(deserialize_char); fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_string(visitor) } fn deserialize_string(self, visitor: V) -> Result where V: Visitor<'de>, { if self.input.is_string() { let string = self.input.to_rust_string_lossy(self.scope); visitor.visit_string(string) } else { Err(Error::ExpectedString) } } wip!(deserialize_bytes); wip!(deserialize_byte_buf); fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { if self.input.is_null_or_undefined() { visitor.visit_none() } else { visitor.visit_some(self) } } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { if self.input.is_null_or_undefined() { visitor.visit_unit() } else { Err(Error::ExpectedNull) } } fn deserialize_unit_struct( self, _name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { self.deserialize_unit(visitor) } // As is done here, serializers are encouraged to treat newtype structs as // insignificant wrappers around the data they contain. That means not // parsing anything other than the contained value. fn deserialize_newtype_struct( self, _name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { visitor.visit_newtype_struct(self) } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { let arr = v8::Local::::try_from(self.input).unwrap(); let len = arr.length(); let obj = v8::Local::::from(arr); let seq = SeqAccess { pos: 0, len, obj, scope: self.scope, }; visitor.visit_seq(seq) } // Like deserialize_seq except it prefers tuple's length over input array's length fn deserialize_tuple(self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { // TODO: error on length mismatch let obj = v8::Local::::try_from(self.input).unwrap(); let seq = SeqAccess { pos: 0, len: len as u32, obj, scope: self.scope, }; visitor.visit_seq(seq) } // Tuple structs look just like sequences in JSON. fn deserialize_tuple_struct( self, _name: &'static str, len: usize, visitor: V, ) -> Result where V: Visitor<'de>, { self.deserialize_tuple(len, visitor) } fn deserialize_map(self, visitor: V) -> Result where V: de::Visitor<'de>, { // Assume object, then get_own_property_names let obj = v8::Local::::try_from(self.input).unwrap(); let prop_names = obj.get_own_property_names(self.scope); let mut keys: Vec = match prop_names { Some(names) => from_v8(self.scope, names.into()).unwrap(), None => vec![], }; let keys: Vec> = keys.drain(..).map(|x| x.into()).collect(); let map = MapAccess { obj, keys, pos: 0, scope: self.scope, }; visitor.visit_map(map) } fn deserialize_struct( self, name: &'static str, fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { // Magic for serde_v8::magic::Value, to passthrough v8::Value // TODO: ensure this is cross-platform and there's no alternative if name == magic::NAME { let mv = magic::Value { v8_value: self.input, }; let hack: u64 = unsafe { std::mem::transmute(mv) }; return visitor.visit_u64(hack); } // Regular struct let obj = v8::Local::::try_from(self.input).unwrap(); let map = ObjectAccess { fields, obj, pos: 0, scope: self.scope, _cache: None, }; visitor.visit_map(map) } fn deserialize_enum( self, _name: &str, _variants: &'static [&'static str], _visitor: V, ) -> Result where V: Visitor<'de>, { unimplemented!(); } // An identifier in Serde is the type that identifies a field of a struct or // the variant of an enum. In JSON, struct fields and enum variants are // represented as strings. In other formats they may be represented as // numeric indices. fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_str(visitor) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_none() } } struct MapAccess<'a, 'b, 's> { obj: v8::Local<'a, v8::Object>, scope: &'b mut v8::HandleScope<'s>, keys: Vec>, pos: usize, } impl<'de> de::MapAccess<'de> for MapAccess<'_, '_, '_> { type Error = Error; fn next_key_seed>( &mut self, seed: K, ) -> Result> { Ok(match self.keys.get(self.pos) { Some(key) => { let mut deserializer = Deserializer::new(self.scope, *key, None); Some(seed.deserialize(&mut deserializer)?) } None => None, }) } fn next_value_seed>( &mut self, seed: V, ) -> Result { if self.pos >= self.keys.len() { return Err(Error::LengthMismatch); } let key = self.keys[self.pos]; self.pos += 1; let v8_val = self.obj.get(self.scope, key).unwrap(); let mut deserializer = Deserializer::new(self.scope, v8_val, None); seed.deserialize(&mut deserializer) } fn next_entry_seed< K: de::DeserializeSeed<'de>, V: de::DeserializeSeed<'de>, >( &mut self, kseed: K, vseed: V, ) -> Result> { if self.pos >= self.keys.len() { return Ok(None); } let v8_key = self.keys[self.pos]; self.pos += 1; let mut kdeserializer = Deserializer::new(self.scope, v8_key, None); Ok(Some((kseed.deserialize(&mut kdeserializer)?, { let v8_val = self.obj.get(self.scope, v8_key).unwrap(); let mut deserializer = Deserializer::new(self.scope, v8_val, None); vseed.deserialize(&mut deserializer)? }))) } } struct ObjectAccess<'a, 'b, 's> { obj: v8::Local<'a, v8::Object>, scope: &'b mut v8::HandleScope<'s>, fields: &'static [&'static str], pos: usize, _cache: Option<&'b mut KeyCache>, } fn str_deserializer(s: &str) -> de::value::StrDeserializer { de::IntoDeserializer::into_deserializer(s) } impl<'de, 'a, 'b, 's> de::MapAccess<'de> for ObjectAccess<'a, 'b, 's> { type Error = Error; fn next_key_seed>( &mut self, seed: K, ) -> Result> { Ok(match self.fields.get(self.pos) { Some(&field) => Some(seed.deserialize(str_deserializer(field))?), None => None, }) } fn next_value_seed>( &mut self, seed: V, ) -> Result { if self.pos >= self.fields.len() { return Err(Error::LengthMismatch); } let field = self.fields[self.pos]; self.pos += 1; let key = v8_struct_key(self.scope, field).into(); let v8_val = self.obj.get(self.scope, key).unwrap(); let mut deserializer = Deserializer::new(self.scope, v8_val, None); seed.deserialize(&mut deserializer) } fn next_entry_seed< K: de::DeserializeSeed<'de>, V: de::DeserializeSeed<'de>, >( &mut self, kseed: K, vseed: V, ) -> Result> { if self.pos >= self.fields.len() { return Ok(None); } let field = self.fields[self.pos]; self.pos += 1; Ok(Some((kseed.deserialize(str_deserializer(field))?, { let key = v8_struct_key(self.scope, field).into(); let v8_val = self.obj.get(self.scope, key).unwrap(); let mut deserializer = Deserializer::new(self.scope, v8_val, None); vseed.deserialize(&mut deserializer)? }))) } } struct SeqAccess<'a, 'b, 's> { obj: v8::Local<'a, v8::Object>, scope: &'b mut v8::HandleScope<'s>, len: u32, pos: u32, } impl<'de> de::SeqAccess<'de> for SeqAccess<'_, '_, '_> { type Error = Error; fn next_element_seed>( &mut self, seed: T, ) -> Result> { let pos = self.pos; self.pos += 1; if pos < self.len { let val = self.obj.get_index(self.scope, pos).unwrap(); let mut deserializer = Deserializer::new(self.scope, val, None); Ok(Some(seed.deserialize(&mut deserializer)?)) } else { Ok(None) } } }