summaryrefslogtreecommitdiff
path: root/serde_v8/src/de.rs
diff options
context:
space:
mode:
Diffstat (limited to 'serde_v8/src/de.rs')
-rw-r--r--serde_v8/src/de.rs617
1 files changed, 0 insertions, 617 deletions
diff --git a/serde_v8/src/de.rs b/serde_v8/src/de.rs
deleted file mode 100644
index b0237d514..000000000
--- a/serde_v8/src/de.rs
+++ /dev/null
@@ -1,617 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-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<T>
-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<T>
-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<V>(self, _v: V) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- unimplemented!()
- }
- };
-}
-
-macro_rules! deserialize_signed {
- ($dmethod:ident, $vmethod:ident, $t:tt) => {
- fn $dmethod<V>(self, visitor: V) -> Result<V::Value>
- 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<V>(self, visitor: V) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- match ValueType::from_v8(self.input) {
- ValueType::Null => self.deserialize_unit(visitor),
- ValueType::Bool => self.deserialize_bool(visitor),
- // Handle floats & ints separately to work with loosely-typed serde_json
- ValueType::Number => {
- if self.input.is_uint32() {
- self.deserialize_u32(visitor)
- } else if self.input.is_int32() {
- self.deserialize_i32(visitor)
- } else {
- 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<V>(self, visitor: V) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- // Relaxed typechecking, will map all non-true vals to false
- visitor.visit_bool(self.input.is_true())
- }
-
- 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<V>(self, visitor: V) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- visitor.visit_f32(self.input.number_value(&mut self.scope).unwrap() as f32)
- }
-
- fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- visitor.visit_f64(self.input.number_value(&mut self.scope).unwrap())
- }
-
- wip!(deserialize_char);
-
- fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- self.deserialize_string(visitor)
- }
-
- fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- if self.input.is_string() {
- let v8_string = v8::Local::<v8::String>::try_from(self.input).unwrap();
- let string = v8_string.to_rust_string_lossy(self.scope);
- visitor.visit_string(string)
- } else {
- Err(Error::ExpectedString)
- }
- }
-
- wip!(deserialize_bytes);
- wip!(deserialize_byte_buf);
-
- fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- if self.input.is_null_or_undefined() {
- visitor.visit_none()
- } else {
- visitor.visit_some(self)
- }
- }
-
- fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- if self.input.is_null_or_undefined() {
- visitor.visit_unit()
- } else {
- Err(Error::ExpectedNull)
- }
- }
-
- fn deserialize_unit_struct<V>(
- self,
- _name: &'static str,
- visitor: V,
- ) -> Result<V::Value>
- 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<V>(
- self,
- _name: &'static str,
- visitor: V,
- ) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- visitor.visit_newtype_struct(self)
- }
-
- fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- let arr = v8::Local::<v8::Array>::try_from(self.input)
- .map_err(|_| Error::ExpectedArray)?;
- let len = arr.length();
- let obj = v8::Local::<v8::Object>::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<V>(self, len: usize, visitor: V) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- // TODO: error on length mismatch
- let obj = v8::Local::<v8::Object>::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<V>(
- self,
- _name: &'static str,
- len: usize,
- visitor: V,
- ) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- self.deserialize_tuple(len, visitor)
- }
-
- fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
- where
- V: de::Visitor<'de>,
- {
- // Assume object, then get_own_property_names
- let obj = v8::Local::<v8::Object>::try_from(self.input).unwrap();
- let prop_names = obj.get_own_property_names(self.scope);
- let mut keys: Vec<magic::Value> = match prop_names {
- Some(names) => from_v8(self.scope, names.into()).unwrap(),
- None => vec![],
- };
- let keys: Vec<v8::Local<v8::Value>> = keys
- .drain(..)
- .map(|x| x.into())
- // Filter keys to drop keys whose value is undefined
- // TODO: optimize, since this doubles our get calls
- .filter(|key| !obj.get(self.scope, *key).unwrap().is_undefined())
- .collect();
-
- let map = MapAccess {
- obj,
- keys,
- pos: 0,
- scope: self.scope,
- };
- visitor.visit_map(map)
- }
-
- fn deserialize_struct<V>(
- self,
- name: &'static str,
- fields: &'static [&'static str],
- visitor: V,
- ) -> Result<V::Value>
- 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);
- }
-
- // Magic Buffer
- if name == magic::buffer::BUF_NAME {
- let zero_copy_buf =
- v8::Local::<v8::ArrayBufferView>::try_from(self.input)
- .map(|view| magic::zero_copy_buf::ZeroCopyBuf::new(self.scope, view))
- .map_err(|_| Error::ExpectedArray)?;
- let data: [u8; 32] = unsafe { std::mem::transmute(zero_copy_buf) };
- return visitor.visit_bytes(&data);
- }
-
- // Regular struct
- let obj = v8::Local::<v8::Object>::try_from(self.input).unwrap();
- let map = ObjectAccess {
- fields,
- obj,
- pos: 0,
- scope: self.scope,
- _cache: None,
- };
-
- visitor.visit_map(map)
- }
-
- /// To be compatible with `serde-json`, we expect enums to be:
- /// - `"Variant"`: strings for unit variants, i.e: Enum::Variant
- /// - `{ Variant: payload }`: single K/V pairs, converted to `Enum::Variant { payload }`
- fn deserialize_enum<V>(
- self,
- _name: &str,
- _variants: &'static [&'static str],
- visitor: V,
- ) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- // Unit variant
- if self.input.is_string() {
- let payload = v8::undefined(self.scope).into();
- visitor.visit_enum(EnumAccess {
- scope: self.scope,
- tag: self.input,
- payload,
- })
- }
- // Struct or tuple variant
- else if self.input.is_object() {
- // Assume object
- let obj = v8::Local::<v8::Object>::try_from(self.input).unwrap();
- // Unpack single-key
- let tag = {
- let prop_names = obj.get_own_property_names(self.scope);
- let prop_names = prop_names.ok_or(Error::ExpectedEnum)?;
- if prop_names.length() != 1 {
- return Err(Error::LengthMismatch);
- }
- prop_names.get_index(self.scope, 0).unwrap()
- };
-
- let payload = obj.get(self.scope, tag).unwrap();
- visitor.visit_enum(EnumAccess {
- scope: self.scope,
- tag,
- payload,
- })
- } else {
- // TODO: improve error
- Err(Error::ExpectedEnum)
- }
- }
-
- // 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<V>(self, visitor: V) -> Result<V::Value>
- where
- V: Visitor<'de>,
- {
- self.deserialize_str(visitor)
- }
-
- fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
- 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<v8::Local<'a, v8::Value>>,
- pos: usize,
-}
-
-impl<'de> de::MapAccess<'de> for MapAccess<'_, '_, '_> {
- type Error = Error;
-
- fn next_key_seed<K: de::DeserializeSeed<'de>>(
- &mut self,
- seed: K,
- ) -> Result<Option<K::Value>> {
- 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<V: de::DeserializeSeed<'de>>(
- &mut self,
- seed: V,
- ) -> Result<V::Value> {
- 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<Option<(K::Value, V::Value)>> {
- 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<Error> {
- 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<K: de::DeserializeSeed<'de>>(
- &mut self,
- seed: K,
- ) -> Result<Option<K::Value>> {
- Ok(match self.fields.get(self.pos) {
- Some(&field) => Some(seed.deserialize(str_deserializer(field))?),
- None => None,
- })
- }
-
- fn next_value_seed<V: de::DeserializeSeed<'de>>(
- &mut self,
- seed: V,
- ) -> Result<V::Value> {
- 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<Option<(K::Value, V::Value)>> {
- 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<T: de::DeserializeSeed<'de>>(
- &mut self,
- seed: T,
- ) -> Result<Option<T::Value>> {
- 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)
- }
- }
-
- fn size_hint(&self) -> Option<usize> {
- Some((self.len - self.pos) as usize)
- }
-}
-
-struct EnumAccess<'a, 'b, 's> {
- tag: v8::Local<'a, v8::Value>,
- payload: v8::Local<'a, v8::Value>,
- scope: &'b mut v8::HandleScope<'s>,
- // p1: std::marker::PhantomData<&'x ()>,
-}
-
-impl<'de, 'a, 'b, 's, 'x> de::EnumAccess<'de> for EnumAccess<'a, 'b, 's> {
- type Error = Error;
- type Variant = VariantDeserializer<'a, 'b, 's>;
-
- fn variant_seed<V: de::DeserializeSeed<'de>>(
- self,
- seed: V,
- ) -> Result<(V::Value, Self::Variant)> {
- let seed = {
- let mut dtag = Deserializer::new(self.scope, self.tag, None);
- seed.deserialize(&mut dtag)
- };
- let dpayload = VariantDeserializer::<'a, 'b, 's> {
- scope: self.scope,
- value: self.payload,
- };
-
- Ok((seed?, dpayload))
- }
-}
-
-struct VariantDeserializer<'a, 'b, 's> {
- value: v8::Local<'a, v8::Value>,
- scope: &'b mut v8::HandleScope<'s>,
-}
-
-impl<'de, 'a, 'b, 's> de::VariantAccess<'de>
- for VariantDeserializer<'a, 'b, 's>
-{
- type Error = Error;
-
- fn unit_variant(self) -> Result<()> {
- let mut d = Deserializer::new(self.scope, self.value, None);
- de::Deserialize::deserialize(&mut d)
- }
-
- fn newtype_variant_seed<T: de::DeserializeSeed<'de>>(
- self,
- seed: T,
- ) -> Result<T::Value> {
- let mut d = Deserializer::new(self.scope, self.value, None);
- seed.deserialize(&mut d)
- }
-
- fn tuple_variant<V: de::Visitor<'de>>(
- self,
- len: usize,
- visitor: V,
- ) -> Result<V::Value> {
- let mut d = Deserializer::new(self.scope, self.value, None);
- de::Deserializer::deserialize_tuple(&mut d, len, visitor)
- }
-
- fn struct_variant<V: de::Visitor<'de>>(
- self,
- fields: &'static [&'static str],
- visitor: V,
- ) -> Result<V::Value> {
- let mut d = Deserializer::new(self.scope, self.value, None);
- de::Deserializer::deserialize_struct(&mut d, "", fields, visitor)
- }
-}