diff options
Diffstat (limited to 'serde_v8/src')
-rw-r--r-- | serde_v8/src/de.rs | 617 | ||||
-rw-r--r-- | serde_v8/src/error.rs | 46 | ||||
-rw-r--r-- | serde_v8/src/keys.rs | 33 | ||||
-rw-r--r-- | serde_v8/src/lib.rs | 17 | ||||
-rw-r--r-- | serde_v8/src/magic/buffer.rs | 139 | ||||
-rw-r--r-- | serde_v8/src/magic/field.rs | 144 | ||||
-rw-r--r-- | serde_v8/src/magic/mod.rs | 8 | ||||
-rw-r--r-- | serde_v8/src/magic/value.rs | 79 | ||||
-rw-r--r-- | serde_v8/src/magic/zero_copy_buf.rs | 102 | ||||
-rw-r--r-- | serde_v8/src/payload.rs | 34 | ||||
-rw-r--r-- | serde_v8/src/ser.rs | 559 | ||||
-rw-r--r-- | serde_v8/src/serializable.rs | 118 | ||||
-rw-r--r-- | serde_v8/src/utils.rs | 34 |
13 files changed, 0 insertions, 1930 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) - } -} diff --git a/serde_v8/src/error.rs b/serde_v8/src/error.rs deleted file mode 100644 index 7dc84e5e5..000000000 --- a/serde_v8/src/error.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use std::fmt::{self, Display}; - -use serde::{de, ser}; - -pub type Result<T> = std::result::Result<T, Error>; - -#[derive(Clone, Debug, PartialEq)] -pub enum Error { - Message(String), - - ExpectedBoolean, - ExpectedInteger, - ExpectedString, - ExpectedNull, - ExpectedArray, - ExpectedMap, - ExpectedEnum, - - ExpectedUtf8, - - LengthMismatch, -} - -impl ser::Error for Error { - fn custom<T: Display>(msg: T) -> Self { - Error::Message(msg.to_string()) - } -} - -impl de::Error for Error { - fn custom<T: Display>(msg: T) -> Self { - Error::Message(msg.to_string()) - } -} - -impl Display for Error { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::Message(msg) => formatter.write_str(msg), - err => formatter.write_str(format!("serde_v8 error: {:?}", err).as_ref()), - } - } -} - -impl std::error::Error for Error {} diff --git a/serde_v8/src/keys.rs b/serde_v8/src/keys.rs deleted file mode 100644 index ea989086c..000000000 --- a/serde_v8/src/keys.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use rusty_v8 as v8; - -use std::collections::HashMap; - -// KeyCache stores a pool struct keys mapped to v8, -// to minimize allocs and speed up decoding/encoding `v8::Object`s -// TODO: experiment with in from_v8/to_v8 -pub struct KeyCache(HashMap<&'static str, v8::Global<v8::String>>); - -// creates an optimized v8::String for a struct field -// TODO: experiment with external strings -// TODO: evaluate if own KeyCache is better than v8's dedupe -pub fn v8_struct_key<'s>( - scope: &mut v8::HandleScope<'s>, - field: &'static str, -) -> v8::Local<'s, v8::String> { - // Internalized v8 strings are significantly faster than "normal" v8 strings - // since v8 deduplicates re-used strings minimizing new allocations - // see: https://github.com/v8/v8/blob/14ac92e02cc3db38131a57e75e2392529f405f2f/include/v8.h#L3165-L3171 - v8::String::new_from_utf8( - scope, - field.as_ref(), - v8::NewStringType::Internalized, - ) - .unwrap() - - // TODO: consider external strings later - // right now non-deduped external strings (without KeyCache) - // are slower than the deduped internalized strings by ~2.5x - // since they're a new string in v8's eyes and needs to be hashed, etc... - // v8::String::new_external_onebyte_static(scope, field).unwrap() -} diff --git a/serde_v8/src/lib.rs b/serde_v8/src/lib.rs deleted file mode 100644 index 93ad4908f..000000000 --- a/serde_v8/src/lib.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -mod de; -mod error; -mod keys; -mod magic; -mod payload; -mod ser; -mod serializable; -pub mod utils; - -pub use de::{from_v8, from_v8_cached, Deserializer}; -pub use error::{Error, Result}; -pub use keys::KeyCache; -pub use magic::buffer::MagicBuffer as Buffer; -pub use magic::Value; -pub use ser::{to_v8, Serializer}; -pub use serializable::{Serializable, SerializablePkg}; diff --git a/serde_v8/src/magic/buffer.rs b/serde_v8/src/magic/buffer.rs deleted file mode 100644 index 1fcfffc72..000000000 --- a/serde_v8/src/magic/buffer.rs +++ /dev/null @@ -1,139 +0,0 @@ -use rusty_v8 as v8; - -use std::fmt; -use std::ops::Deref; -use std::ops::DerefMut; -use std::sync::Mutex; - -use super::zero_copy_buf::ZeroCopyBuf; - -// An asymmetric wrapper around ZeroCopyBuf, -// allowing us to use a single type for familiarity -pub enum MagicBuffer { - FromV8(ZeroCopyBuf), - ToV8(Mutex<Option<Box<[u8]>>>), -} - -impl MagicBuffer { - pub fn new<'s>( - scope: &mut v8::HandleScope<'s>, - view: v8::Local<v8::ArrayBufferView>, - ) -> Self { - Self::FromV8(ZeroCopyBuf::new(scope, view)) - } - - pub fn empty() -> Self { - MagicBuffer::ToV8(Mutex::new(Some(vec![0_u8; 0].into_boxed_slice()))) - } -} - -impl Clone for MagicBuffer { - fn clone(&self) -> Self { - match self { - Self::FromV8(zbuf) => Self::FromV8(zbuf.clone()), - Self::ToV8(_) => panic!("Don't Clone a MagicBuffer sent to v8"), - } - } -} - -impl AsRef<[u8]> for MagicBuffer { - fn as_ref(&self) -> &[u8] { - &*self - } -} - -impl AsMut<[u8]> for MagicBuffer { - fn as_mut(&mut self) -> &mut [u8] { - &mut *self - } -} - -impl Deref for MagicBuffer { - type Target = [u8]; - fn deref(&self) -> &[u8] { - match self { - Self::FromV8(buf) => &*buf, - Self::ToV8(_) => panic!("Don't Deref a MagicBuffer sent to v8"), - } - } -} - -impl DerefMut for MagicBuffer { - fn deref_mut(&mut self) -> &mut [u8] { - match self { - Self::FromV8(buf) => &mut *buf, - Self::ToV8(_) => panic!("Don't Deref a MagicBuffer sent to v8"), - } - } -} - -impl From<Box<[u8]>> for MagicBuffer { - fn from(buf: Box<[u8]>) -> Self { - MagicBuffer::ToV8(Mutex::new(Some(buf))) - } -} - -impl From<Vec<u8>> for MagicBuffer { - fn from(vec: Vec<u8>) -> Self { - vec.into_boxed_slice().into() - } -} - -pub const BUF_NAME: &str = "$__v8_magic_Buffer"; -pub const BUF_FIELD_1: &str = "$__v8_magic_buffer_1"; -pub const BUF_FIELD_2: &str = "$__v8_magic_buffer_2"; - -impl serde::Serialize for MagicBuffer { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - - let mut s = serializer.serialize_struct(BUF_NAME, 1)?; - let boxed: Box<[u8]> = match self { - Self::FromV8(buf) => { - let value: &[u8] = &buf; - value.into() - } - Self::ToV8(x) => x.lock().unwrap().take().expect("MagicBuffer was empty"), - }; - let hack: [usize; 2] = unsafe { std::mem::transmute(boxed) }; - let f1: u64 = hack[0] as u64; - let f2: u64 = hack[1] as u64; - s.serialize_field(BUF_FIELD_1, &f1)?; - s.serialize_field(BUF_FIELD_2, &f2)?; - s.end() - } -} - -impl<'de, 's> serde::Deserialize<'de> for MagicBuffer { - fn deserialize<D>(deserializer: D) -> Result<MagicBuffer, D::Error> - where - D: serde::Deserializer<'de>, - { - struct ValueVisitor {} - - impl<'de> serde::de::Visitor<'de> for ValueVisitor { - type Value = MagicBuffer; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("a serde_v8::MagicBuffer") - } - - fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> - where - E: serde::de::Error, - { - let p1: &[usize] = unsafe { &*(v as *const [u8] as *const [usize]) }; - let p2: [usize; 4] = [p1[0], p1[1], p1[2], p1[3]]; - let zero_copy: ZeroCopyBuf = unsafe { std::mem::transmute(p2) }; - Ok(MagicBuffer::FromV8(zero_copy)) - } - } - - static FIELDS: [&str; 0] = []; - let visitor = ValueVisitor {}; - deserializer.deserialize_struct(BUF_NAME, &FIELDS, visitor) - } -} diff --git a/serde_v8/src/magic/field.rs b/serde_v8/src/magic/field.rs deleted file mode 100644 index e6bb9ee54..000000000 --- a/serde_v8/src/magic/field.rs +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use crate::error::{Error, Result}; -use serde::ser::{Impossible, Serialize, Serializer}; - -/// All serde_v8 "magic" values are reduced to structs with 1 or 2 u64 fields -/// assuming usize==u64, most types are simply a pointer or pointer+len (e.g: Box<T>) -pub type TransmutedField = u64; -pub type FieldResult = Result<TransmutedField>; - -macro_rules! not_reachable { - ($($name:ident($ty:ty);)*) => { - $(fn $name(self, _v: $ty) -> FieldResult { - unreachable!(); - })* - }; -} - -/// FieldSerializer is a simple serde::Serializer that only returns u64s -/// it allows the "magic" struct serializers to obtain the transmuted field values -pub struct FieldSerializer {} - -impl Serializer for FieldSerializer { - type Ok = TransmutedField; - type Error = Error; - - type SerializeSeq = Impossible<TransmutedField, Error>; - type SerializeTuple = Impossible<TransmutedField, Error>; - type SerializeTupleStruct = Impossible<TransmutedField, Error>; - type SerializeTupleVariant = Impossible<TransmutedField, Error>; - type SerializeMap = Impossible<TransmutedField, Error>; - type SerializeStruct = Impossible<TransmutedField, Error>; - type SerializeStructVariant = Impossible<TransmutedField, Error>; - - fn serialize_u64(self, transmuted_field: u64) -> FieldResult { - Ok(transmuted_field) - } - - not_reachable! { - serialize_i8(i8); - serialize_i16(i16); - serialize_i32(i32); - serialize_i64(i64); - serialize_u8(u8); - serialize_u16(u16); - serialize_u32(u32); - // serialize_u64(TransmutedField); the chosen one - serialize_f32(f32); - serialize_f64(f64); - serialize_bool(bool); - serialize_char(char); - serialize_str(&str); - serialize_bytes(&[u8]); - } - - fn serialize_none(self) -> FieldResult { - unreachable!(); - } - - fn serialize_some<T: ?Sized + Serialize>(self, _value: &T) -> FieldResult { - unreachable!(); - } - - fn serialize_unit(self) -> FieldResult { - unreachable!(); - } - - fn serialize_unit_struct(self, _name: &'static str) -> FieldResult { - unreachable!(); - } - - fn serialize_unit_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - ) -> FieldResult { - unreachable!(); - } - - fn serialize_newtype_struct<T: ?Sized + Serialize>( - self, - _name: &'static str, - _value: &T, - ) -> FieldResult { - unreachable!(); - } - - fn serialize_newtype_variant<T: ?Sized + Serialize>( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _value: &T, - ) -> FieldResult { - unreachable!(); - } - fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> { - unreachable!(); - } - - fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> { - unreachable!(); - } - - fn serialize_tuple_struct( - self, - _name: &'static str, - _len: usize, - ) -> Result<Self::SerializeTupleStruct> { - unreachable!(); - } - - fn serialize_tuple_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _len: usize, - ) -> Result<Self::SerializeTupleVariant> { - unreachable!(); - } - - fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> { - unreachable!(); - } - - fn serialize_struct( - self, - _name: &'static str, - _len: usize, - ) -> Result<Self::SerializeStruct> { - unreachable!(); - } - - fn serialize_struct_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _len: usize, - ) -> Result<Self::SerializeStructVariant> { - unreachable!(); - } -} diff --git a/serde_v8/src/magic/mod.rs b/serde_v8/src/magic/mod.rs deleted file mode 100644 index 29c35a831..000000000 --- a/serde_v8/src/magic/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -pub mod buffer; -mod field; -mod value; -pub mod zero_copy_buf; - -pub use field::FieldSerializer; -pub use value::{Value, FIELD, NAME}; diff --git a/serde_v8/src/magic/value.rs b/serde_v8/src/magic/value.rs deleted file mode 100644 index 2cb622466..000000000 --- a/serde_v8/src/magic/value.rs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use rusty_v8 as v8; - -use std::fmt; -use std::marker::PhantomData; - -pub const FIELD: &str = "$__v8_magic_value"; -pub const NAME: &str = "$__v8_magic_Value"; - -/// serde_v8::Value allows passing through `v8::Value`s untouched -/// when encoding/decoding and allows mixing rust & v8 values in -/// structs, tuples... -/// The implementation mainly breaks down to: -/// 1. Transmuting between u64 <> serde_v8::Value -/// 2. Using special struct/field names to detect these values -/// 3. Then serde "boilerplate" -pub struct Value<'s> { - pub v8_value: v8::Local<'s, v8::Value>, -} - -impl<'s> From<v8::Local<'s, v8::Value>> for Value<'s> { - fn from(v8_value: v8::Local<'s, v8::Value>) -> Self { - Self { v8_value } - } -} - -impl<'s> From<Value<'s>> for v8::Local<'s, v8::Value> { - fn from(v: Value<'s>) -> Self { - v.v8_value - } -} - -impl serde::Serialize for Value<'_> { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - - let mut s = serializer.serialize_struct(NAME, 1)?; - let mv = Value { - v8_value: self.v8_value, - }; - let hack: u64 = unsafe { std::mem::transmute(mv) }; - s.serialize_field(FIELD, &hack)?; - s.end() - } -} - -impl<'de, 's> serde::Deserialize<'de> for Value<'s> { - fn deserialize<D>(deserializer: D) -> Result<Value<'s>, D::Error> - where - D: serde::Deserializer<'de>, - { - struct ValueVisitor<'s> { - p1: PhantomData<&'s ()>, - } - - impl<'de, 's> serde::de::Visitor<'de> for ValueVisitor<'s> { - type Value = Value<'s>; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("a v8::Value") - } - - fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> - where - E: serde::de::Error, - { - let mv: Value<'s> = unsafe { std::mem::transmute(v) }; - Ok(mv) - } - } - - static FIELDS: [&str; 1] = [FIELD]; - let visitor = ValueVisitor { p1: PhantomData }; - deserializer.deserialize_struct(NAME, &FIELDS, visitor) - } -} diff --git a/serde_v8/src/magic/zero_copy_buf.rs b/serde_v8/src/magic/zero_copy_buf.rs deleted file mode 100644 index 1f07292ba..000000000 --- a/serde_v8/src/magic/zero_copy_buf.rs +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. - -use rusty_v8 as v8; -use std::cell::Cell; -use std::ops::Deref; -use std::ops::DerefMut; - -/// A ZeroCopyBuf encapsulates a slice that's been borrowed from a JavaScript -/// ArrayBuffer object. JavaScript objects can normally be garbage collected, -/// but the existence of a ZeroCopyBuf inhibits this until it is dropped. It -/// behaves much like an Arc<[u8]>. -/// -/// # Cloning -/// Cloning a ZeroCopyBuf does not clone the contents of the buffer, -/// it creates a new reference to that buffer. -/// -/// To actually clone the contents of the buffer do -/// `let copy = Vec::from(&*zero_copy_buf);` -#[derive(Clone)] -pub struct ZeroCopyBuf { - backing_store: v8::SharedRef<v8::BackingStore>, - byte_offset: usize, - byte_length: usize, -} - -unsafe impl Send for ZeroCopyBuf {} - -impl ZeroCopyBuf { - pub fn new<'s>( - scope: &mut v8::HandleScope<'s>, - view: v8::Local<v8::ArrayBufferView>, - ) -> Self { - let backing_store = view.buffer(scope).unwrap().get_backing_store(); - let byte_offset = view.byte_offset(); - let byte_length = view.byte_length(); - Self { - backing_store, - byte_offset, - byte_length, - } - } -} - -impl Deref for ZeroCopyBuf { - type Target = [u8]; - fn deref(&self) -> &[u8] { - unsafe { - get_backing_store_slice( - &self.backing_store, - self.byte_offset, - self.byte_length, - ) - } - } -} - -impl DerefMut for ZeroCopyBuf { - fn deref_mut(&mut self) -> &mut [u8] { - unsafe { - get_backing_store_slice_mut( - &self.backing_store, - self.byte_offset, - self.byte_length, - ) - } - } -} - -impl AsRef<[u8]> for ZeroCopyBuf { - fn as_ref(&self) -> &[u8] { - &*self - } -} - -impl AsMut<[u8]> for ZeroCopyBuf { - fn as_mut(&mut self) -> &mut [u8] { - &mut *self - } -} - -unsafe fn get_backing_store_slice( - backing_store: &v8::SharedRef<v8::BackingStore>, - byte_offset: usize, - byte_length: usize, -) -> &[u8] { - let cells: *const [Cell<u8>] = - &backing_store[byte_offset..byte_offset + byte_length]; - let bytes = cells as *const [u8]; - &*bytes -} - -#[allow(clippy::mut_from_ref)] -unsafe fn get_backing_store_slice_mut( - backing_store: &v8::SharedRef<v8::BackingStore>, - byte_offset: usize, - byte_length: usize, -) -> &mut [u8] { - let cells: *const [Cell<u8>] = - &backing_store[byte_offset..byte_offset + byte_length]; - let bytes = cells as *const _ as *mut [u8]; - &mut *bytes -} diff --git a/serde_v8/src/payload.rs b/serde_v8/src/payload.rs deleted file mode 100644 index 816158f93..000000000 --- a/serde_v8/src/payload.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use rusty_v8 as v8; - -// TODO: maybe add a Payload type that holds scope & v8::Value -// so it can implement Deserialize by itself - -// Classifies v8::Values into sub-types -pub enum ValueType { - Null, - Bool, - Number, - String, - Array, - Object, -} - -impl ValueType { - pub fn from_v8(v: v8::Local<v8::Value>) -> ValueType { - if v.is_boolean() { - return Self::Bool; - } else if v.is_number() { - return Self::Number; - } else if v.is_string() { - return Self::String; - } else if v.is_array() { - return Self::Array; - } else if v.is_object() { - return Self::Object; - } else if v.is_null_or_undefined() { - return Self::Null; - } - panic!("serde_v8: unknown ValueType for v8::Value") - } -} diff --git a/serde_v8/src/ser.rs b/serde_v8/src/ser.rs deleted file mode 100644 index b0f1a5e7d..000000000 --- a/serde_v8/src/ser.rs +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use rusty_v8 as v8; -use serde::ser; -use serde::ser::Serialize; - -use std::cell::RefCell; - -use crate::error::{Error, Result}; -use crate::keys::v8_struct_key; -use crate::magic; - -type JsValue<'s> = v8::Local<'s, v8::Value>; -type JsResult<'s> = Result<JsValue<'s>>; - -type ScopePtr<'a, 'b, 'c> = &'c RefCell<&'b mut v8::HandleScope<'a>>; - -pub fn to_v8<'a, T>(scope: &mut v8::HandleScope<'a>, input: T) -> JsResult<'a> -where - T: Serialize, -{ - let scopeptr = RefCell::new(scope); - let serializer = Serializer::new(&scopeptr); - - input.serialize(serializer) -} - -/// Wraps other serializers into an enum tagged variant form. -/// Uses {"Variant": ...payload...} for compatibility with serde-json. -pub struct VariantSerializer<'a, 'b, 'c, S> { - inner: S, - scope: ScopePtr<'a, 'b, 'c>, - variant: &'static str, -} - -impl<'a, 'b, 'c, S> VariantSerializer<'a, 'b, 'c, S> { - pub fn new( - scope: ScopePtr<'a, 'b, 'c>, - variant: &'static str, - inner: S, - ) -> Self { - Self { - inner, - scope, - variant, - } - } - - fn end(self, inner: impl FnOnce(S) -> JsResult<'a>) -> JsResult<'a> { - let value = inner(self.inner)?; - let scope = &mut *self.scope.borrow_mut(); - let obj = v8::Object::new(scope); - let key = v8_struct_key(scope, self.variant).into(); - obj.set(scope, key, value); - Ok(obj.into()) - } -} - -impl<'a, 'b, 'c, S> ser::SerializeTupleVariant - for VariantSerializer<'a, 'b, 'c, S> -where - S: ser::SerializeTupleStruct<Ok = JsValue<'a>, Error = Error>, -{ - type Ok = JsValue<'a>; - type Error = Error; - - fn serialize_field<T: ?Sized + Serialize>( - &mut self, - value: &T, - ) -> Result<()> { - self.inner.serialize_field(value) - } - - fn end(self) -> JsResult<'a> { - self.end(S::end) - } -} - -impl<'a, 'b, 'c, S> ser::SerializeStructVariant - for VariantSerializer<'a, 'b, 'c, S> -where - S: ser::SerializeStruct<Ok = JsValue<'a>, Error = Error>, -{ - type Ok = JsValue<'a>; - type Error = Error; - - fn serialize_field<T: ?Sized + Serialize>( - &mut self, - key: &'static str, - value: &T, - ) -> Result<()> { - self.inner.serialize_field(key, value) - } - - fn end(self) -> JsResult<'a> { - self.end(S::end) - } -} - -pub struct ArraySerializer<'a, 'b, 'c> { - pending: Vec<JsValue<'a>>, - scope: ScopePtr<'a, 'b, 'c>, -} - -impl<'a, 'b, 'c> ArraySerializer<'a, 'b, 'c> { - pub fn new(scope: ScopePtr<'a, 'b, 'c>, len: Option<usize>) -> Self { - let pending = match len { - Some(len) => Vec::with_capacity(len), - None => vec![], - }; - Self { pending, scope } - } -} - -impl<'a, 'b, 'c> ser::SerializeSeq for ArraySerializer<'a, 'b, 'c> { - type Ok = JsValue<'a>; - type Error = Error; - - fn serialize_element<T: ?Sized + Serialize>( - &mut self, - value: &T, - ) -> Result<()> { - let x = value.serialize(Serializer::new(self.scope))?; - self.pending.push(x); - Ok(()) - } - - fn end(self) -> JsResult<'a> { - let elements = self.pending.iter().as_slice(); - let scope = &mut *self.scope.borrow_mut(); - let arr = v8::Array::new_with_elements(scope, elements); - Ok(arr.into()) - } -} - -impl<'a, 'b, 'c> ser::SerializeTuple for ArraySerializer<'a, 'b, 'c> { - type Ok = JsValue<'a>; - type Error = Error; - - fn serialize_element<T: ?Sized + Serialize>( - &mut self, - value: &T, - ) -> Result<()> { - ser::SerializeSeq::serialize_element(self, value) - } - - fn end(self) -> JsResult<'a> { - ser::SerializeSeq::end(self) - } -} - -impl<'a, 'b, 'c> ser::SerializeTupleStruct for ArraySerializer<'a, 'b, 'c> { - type Ok = JsValue<'a>; - type Error = Error; - - fn serialize_field<T: ?Sized + Serialize>( - &mut self, - value: &T, - ) -> Result<()> { - ser::SerializeTuple::serialize_element(self, value) - } - - fn end(self) -> JsResult<'a> { - ser::SerializeTuple::end(self) - } -} - -pub struct ObjectSerializer<'a, 'b, 'c> { - scope: ScopePtr<'a, 'b, 'c>, - obj: v8::Local<'a, v8::Object>, -} - -impl<'a, 'b, 'c> ObjectSerializer<'a, 'b, 'c> { - pub fn new(scope: ScopePtr<'a, 'b, 'c>) -> Self { - let obj = v8::Object::new(&mut *scope.borrow_mut()); - Self { scope, obj } - } -} - -impl<'a, 'b, 'c> ser::SerializeStruct for ObjectSerializer<'a, 'b, 'c> { - type Ok = JsValue<'a>; - type Error = Error; - - fn serialize_field<T: ?Sized + Serialize>( - &mut self, - key: &'static str, - value: &T, - ) -> Result<()> { - let value = value.serialize(Serializer::new(self.scope))?; - let scope = &mut *self.scope.borrow_mut(); - let key = v8_struct_key(scope, key).into(); - self.obj.set(scope, key, value); - Ok(()) - } - - fn end(self) -> JsResult<'a> { - Ok(self.obj.into()) - } -} - -pub struct MagicSerializer<'a> { - v8_value: Option<v8::Local<'a, v8::Value>>, -} - -impl<'a> ser::SerializeStruct for MagicSerializer<'a> { - type Ok = JsValue<'a>; - type Error = Error; - - fn serialize_field<T: ?Sized + Serialize>( - &mut self, - key: &'static str, - value: &T, - ) -> Result<()> { - if key != magic::FIELD { - unreachable!(); - } - let transmuted: u64 = value.serialize(magic::FieldSerializer {})?; - let mv: magic::Value<'a> = unsafe { std::mem::transmute(transmuted) }; - self.v8_value = Some(mv.v8_value); - Ok(()) - } - - fn end(self) -> JsResult<'a> { - Ok(self.v8_value.unwrap()) - } -} - -// TODO(@AaronO): refactor this and streamline how we transmute values -pub struct MagicBufferSerializer<'a, 'b, 'c> { - scope: ScopePtr<'a, 'b, 'c>, - f1: u64, - f2: u64, -} - -impl<'a, 'b, 'c> MagicBufferSerializer<'a, 'b, 'c> { - pub fn new(scope: ScopePtr<'a, 'b, 'c>) -> Self { - Self { - scope, - f1: 0, - f2: 0, - } - } -} - -impl<'a, 'b, 'c> ser::SerializeStruct for MagicBufferSerializer<'a, 'b, 'c> { - type Ok = JsValue<'a>; - type Error = Error; - - fn serialize_field<T: ?Sized + Serialize>( - &mut self, - key: &'static str, - value: &T, - ) -> Result<()> { - // Get u64 chunk - let transmuted: u64 = value.serialize(magic::FieldSerializer {})?; - match key { - magic::buffer::BUF_FIELD_1 => self.f1 = transmuted, - magic::buffer::BUF_FIELD_2 => self.f2 = transmuted, - _ => unreachable!(), - } - Ok(()) - } - - fn end(self) -> JsResult<'a> { - let x: [usize; 2] = [self.f1 as usize, self.f2 as usize]; - let buf: Box<[u8]> = unsafe { std::mem::transmute(x) }; - let scope = &mut *self.scope.borrow_mut(); - let v8_value = boxed_slice_to_uint8array(scope, buf); - Ok(v8_value.into()) - } -} - -// Dispatches between magic and regular struct serializers -pub enum StructSerializers<'a, 'b, 'c> { - Magic(MagicSerializer<'a>), - MagicBuffer(MagicBufferSerializer<'a, 'b, 'c>), - Regular(ObjectSerializer<'a, 'b, 'c>), -} - -impl<'a, 'b, 'c> ser::SerializeStruct for StructSerializers<'a, 'b, 'c> { - type Ok = JsValue<'a>; - type Error = Error; - - fn serialize_field<T: ?Sized + Serialize>( - &mut self, - key: &'static str, - value: &T, - ) -> Result<()> { - match self { - StructSerializers::Magic(s) => s.serialize_field(key, value), - StructSerializers::MagicBuffer(s) => s.serialize_field(key, value), - StructSerializers::Regular(s) => s.serialize_field(key, value), - } - } - - fn end(self) -> JsResult<'a> { - match self { - StructSerializers::Magic(s) => s.end(), - StructSerializers::MagicBuffer(s) => s.end(), - StructSerializers::Regular(s) => s.end(), - } - } -} - -// Serializes to JS Objects, NOT JS Maps ... -pub struct MapSerializer<'a, 'b, 'c> { - scope: ScopePtr<'a, 'b, 'c>, - obj: v8::Local<'a, v8::Object>, - next_key: Option<JsValue<'a>>, -} - -impl<'a, 'b, 'c> MapSerializer<'a, 'b, 'c> { - pub fn new(scope: ScopePtr<'a, 'b, 'c>) -> Self { - let obj = v8::Object::new(&mut *scope.borrow_mut()); - Self { - scope, - obj, - next_key: None, - } - } -} - -impl<'a, 'b, 'c> ser::SerializeMap for MapSerializer<'a, 'b, 'c> { - type Ok = JsValue<'a>; - type Error = Error; - - fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<()> { - debug_assert!(self.next_key.is_none()); - self.next_key = Some(key.serialize(Serializer::new(self.scope))?); - Ok(()) - } - - fn serialize_value<T: ?Sized + Serialize>( - &mut self, - value: &T, - ) -> Result<()> { - let v8_value = value.serialize(Serializer::new(self.scope))?; - let scope = &mut *self.scope.borrow_mut(); - self.obj.set(scope, self.next_key.take().unwrap(), v8_value); - Ok(()) - } - - fn end(self) -> JsResult<'a> { - debug_assert!(self.next_key.is_none()); - Ok(self.obj.into()) - } -} - -pub struct Serializer<'a, 'b, 'c> { - scope: ScopePtr<'a, 'b, 'c>, -} - -impl<'a, 'b, 'c> Serializer<'a, 'b, 'c> { - pub fn new(scope: ScopePtr<'a, 'b, 'c>) -> Self { - Serializer { scope } - } -} - -macro_rules! forward_to { - ($($name:ident($ty:ty, $to:ident, $lt:lifetime);)*) => { - $(fn $name(self, v: $ty) -> JsResult<$lt> { - self.$to(v as _) - })* - }; -} - -impl<'a, 'b, 'c> ser::Serializer for Serializer<'a, 'b, 'c> { - type Ok = v8::Local<'a, v8::Value>; - type Error = Error; - - type SerializeSeq = ArraySerializer<'a, 'b, 'c>; - type SerializeTuple = ArraySerializer<'a, 'b, 'c>; - type SerializeTupleStruct = ArraySerializer<'a, 'b, 'c>; - type SerializeTupleVariant = - VariantSerializer<'a, 'b, 'c, ArraySerializer<'a, 'b, 'c>>; - type SerializeMap = MapSerializer<'a, 'b, 'c>; - type SerializeStruct = StructSerializers<'a, 'b, 'c>; - type SerializeStructVariant = - VariantSerializer<'a, 'b, 'c, StructSerializers<'a, 'b, 'c>>; - - forward_to! { - serialize_i8(i8, serialize_i32, 'a); - serialize_i16(i16, serialize_i32, 'a); - - serialize_u8(u8, serialize_u32, 'a); - serialize_u16(u16, serialize_u32, 'a); - - serialize_f32(f32, serialize_f64, 'a); - serialize_u64(u64, serialize_f64, 'a); - serialize_i64(i64, serialize_f64, 'a); - } - - fn serialize_i32(self, v: i32) -> JsResult<'a> { - Ok(v8::Integer::new(&mut self.scope.borrow_mut(), v).into()) - } - - fn serialize_u32(self, v: u32) -> JsResult<'a> { - Ok(v8::Integer::new_from_unsigned(&mut self.scope.borrow_mut(), v).into()) - } - - fn serialize_f64(self, v: f64) -> JsResult<'a> { - Ok(v8::Number::new(&mut self.scope.borrow_mut(), v).into()) - } - - fn serialize_bool(self, v: bool) -> JsResult<'a> { - Ok(v8::Boolean::new(&mut self.scope.borrow_mut(), v).into()) - } - - fn serialize_char(self, _v: char) -> JsResult<'a> { - unimplemented!(); - } - - fn serialize_str(self, v: &str) -> JsResult<'a> { - v8::String::new(&mut self.scope.borrow_mut(), v) - .map(|v| v.into()) - .ok_or(Error::ExpectedString) - } - - fn serialize_bytes(self, _v: &[u8]) -> JsResult<'a> { - // TODO: investigate using Uint8Arrays - unimplemented!() - } - - fn serialize_none(self) -> JsResult<'a> { - Ok(v8::null(&mut self.scope.borrow_mut()).into()) - } - - fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> JsResult<'a> { - value.serialize(self) - } - - fn serialize_unit(self) -> JsResult<'a> { - Ok(v8::null(&mut self.scope.borrow_mut()).into()) - } - - fn serialize_unit_struct(self, _name: &'static str) -> JsResult<'a> { - Ok(v8::null(&mut self.scope.borrow_mut()).into()) - } - - /// For compatibility with serde-json, serialises unit variants as "Variant" strings. - fn serialize_unit_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - ) -> JsResult<'a> { - Ok(v8_struct_key(&mut self.scope.borrow_mut(), variant).into()) - } - - fn serialize_newtype_struct<T: ?Sized + Serialize>( - self, - _name: &'static str, - value: &T, - ) -> JsResult<'a> { - value.serialize(self) - } - - fn serialize_newtype_variant<T: ?Sized + Serialize>( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - value: &T, - ) -> JsResult<'a> { - let scope = self.scope; - let x = self.serialize_newtype_struct(variant, value)?; - VariantSerializer::new(scope, variant, x).end(Ok) - } - - /// Serialises any Rust iterable into a JS Array - fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> { - Ok(ArraySerializer::new(self.scope, len)) - } - - fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> { - self.serialize_seq(Some(len)) - } - - fn serialize_tuple_struct( - self, - _name: &'static str, - len: usize, - ) -> Result<Self::SerializeTupleStruct> { - self.serialize_tuple(len) - } - - fn serialize_tuple_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - len: usize, - ) -> Result<Self::SerializeTupleVariant> { - Ok(VariantSerializer::new( - self.scope, - variant, - self.serialize_tuple_struct(variant, len)?, - )) - } - - fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> { - // Serializes a rust Map (e.g: BTreeMap, HashMap) to a v8 Object - // TODO: consider allowing serializing to v8 Maps (e.g: via a magic type) - // since they're lighter and better suited for K/V data - // and maybe restrict keys (e.g: strings and numbers) - Ok(MapSerializer::new(self.scope)) - } - - /// Serialises Rust typed structs into plain JS objects. - fn serialize_struct( - self, - name: &'static str, - _len: usize, - ) -> Result<Self::SerializeStruct> { - match name { - magic::NAME => { - let m: MagicSerializer<'a> = MagicSerializer { v8_value: None }; - Ok(StructSerializers::Magic(m)) - } - magic::buffer::BUF_NAME => { - let m = MagicBufferSerializer::new(self.scope); - Ok(StructSerializers::MagicBuffer(m)) - } - _ => { - let o = ObjectSerializer::new(self.scope); - Ok(StructSerializers::Regular(o)) - } - } - } - - fn serialize_struct_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - len: usize, - ) -> Result<Self::SerializeStructVariant> { - let scope = self.scope; - let x = self.serialize_struct(variant, len)?; - Ok(VariantSerializer::new(scope, variant, x)) - } -} - -// Used to map MagicBuffers to v8 -pub fn boxed_slice_to_uint8array<'a>( - scope: &mut v8::HandleScope<'a>, - buf: Box<[u8]>, -) -> v8::Local<'a, v8::Uint8Array> { - if buf.is_empty() { - let ab = v8::ArrayBuffer::new(scope, 0); - return v8::Uint8Array::new(scope, ab, 0, 0) - .expect("Failed to create UintArray8"); - } - let buf_len = buf.len(); - let backing_store = v8::ArrayBuffer::new_backing_store_from_boxed_slice(buf); - let backing_store_shared = backing_store.make_shared(); - let ab = v8::ArrayBuffer::with_backing_store(scope, &backing_store_shared); - v8::Uint8Array::new(scope, ab, 0, buf_len) - .expect("Failed to create UintArray8") -} diff --git a/serde_v8/src/serializable.rs b/serde_v8/src/serializable.rs deleted file mode 100644 index c9182b636..000000000 --- a/serde_v8/src/serializable.rs +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use rusty_v8 as v8; -use std::any::TypeId; -use std::mem::transmute_copy; - -/// Serializable exists to allow boxing values as "objects" to be serialized later, -/// this is particularly useful for async op-responses. This trait is a more efficient -/// replacement for erased-serde that makes less allocations, since it's specific to serde_v8 -/// (and thus doesn't have to have generic outputs, etc...) -pub trait Serializable { - fn to_v8<'a>( - &self, - scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error>; -} - -/// Allows all implementors of `serde::Serialize` to implement Serializable -impl<T: serde::Serialize> Serializable for T { - fn to_v8<'a>( - &self, - scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error> { - crate::to_v8(scope, self) - } -} - -/// SerializablePkg exists to provide a fast path for op returns, -/// allowing them to avoid boxing primtives (ints/floats/bool/unit/...) -pub enum SerializablePkg { - Primitive(Primitive), - Serializable(Box<dyn Serializable>), -} - -impl SerializablePkg { - pub fn to_v8<'a>( - &self, - scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error> { - match &*self { - Self::Primitive(x) => crate::to_v8(scope, x), - Self::Serializable(x) => x.to_v8(scope), - } - } -} - -/// Primitive serves as a lightweight serializable wrapper around primitives -/// so that we can use them for async values -#[derive(Clone, Copy)] -pub enum Primitive { - Unit, - Bool(bool), - Int8(i8), - Int16(i16), - Int32(i32), - Int64(i64), - UInt8(u8), - UInt16(u16), - UInt32(u32), - UInt64(u64), - Float32(f32), - Float64(f64), -} - -impl serde::Serialize for Primitive { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: serde::Serializer, - { - match *self { - Self::Unit => serializer.serialize_unit(), - Self::Bool(x) => serializer.serialize_bool(x), - Self::Int8(x) => serializer.serialize_i8(x), - Self::Int16(x) => serializer.serialize_i16(x), - Self::Int32(x) => serializer.serialize_i32(x), - Self::Int64(x) => serializer.serialize_i64(x), - Self::UInt8(x) => serializer.serialize_u8(x), - Self::UInt16(x) => serializer.serialize_u16(x), - Self::UInt32(x) => serializer.serialize_u32(x), - Self::UInt64(x) => serializer.serialize_u64(x), - Self::Float32(x) => serializer.serialize_f32(x), - Self::Float64(x) => serializer.serialize_f64(x), - } - } -} - -impl<T: serde::Serialize + 'static> From<T> for SerializablePkg { - fn from(x: T) -> Self { - let tid = TypeId::of::<T>(); - - if tid == TypeId::of::<()>() { - Self::Primitive(Primitive::Unit) - } else if tid == TypeId::of::<bool>() { - Self::Primitive(Primitive::Bool(unsafe { transmute_copy(&x) })) - } else if tid == TypeId::of::<i8>() { - Self::Primitive(Primitive::Int8(unsafe { transmute_copy(&x) })) - } else if tid == TypeId::of::<i16>() { - Self::Primitive(Primitive::Int16(unsafe { transmute_copy(&x) })) - } else if tid == TypeId::of::<i32>() { - Self::Primitive(Primitive::Int32(unsafe { transmute_copy(&x) })) - } else if tid == TypeId::of::<i64>() { - Self::Primitive(Primitive::Int64(unsafe { transmute_copy(&x) })) - } else if tid == TypeId::of::<u8>() { - Self::Primitive(Primitive::UInt8(unsafe { transmute_copy(&x) })) - } else if tid == TypeId::of::<u16>() { - Self::Primitive(Primitive::UInt16(unsafe { transmute_copy(&x) })) - } else if tid == TypeId::of::<u32>() { - Self::Primitive(Primitive::UInt32(unsafe { transmute_copy(&x) })) - } else if tid == TypeId::of::<u64>() { - Self::Primitive(Primitive::UInt64(unsafe { transmute_copy(&x) })) - } else if tid == TypeId::of::<f32>() { - Self::Primitive(Primitive::Float32(unsafe { transmute_copy(&x) })) - } else if tid == TypeId::of::<f64>() { - Self::Primitive(Primitive::Float64(unsafe { transmute_copy(&x) })) - } else { - Self::Serializable(Box::new(x)) - } - } -} diff --git a/serde_v8/src/utils.rs b/serde_v8/src/utils.rs deleted file mode 100644 index 8f2a7a1eb..000000000 --- a/serde_v8/src/utils.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use rusty_v8 as v8; -use std::sync::Once; - -pub fn js_exec<'s>( - scope: &mut v8::HandleScope<'s>, - src: &str, -) -> v8::Local<'s, v8::Value> { - let code = v8::String::new(scope, src).unwrap(); - let script = v8::Script::compile(scope, code, None).unwrap(); - script.run(scope).unwrap() -} - -pub fn v8_init() { - let platform = v8::new_default_platform().unwrap(); - v8::V8::initialize_platform(platform); - v8::V8::initialize(); -} - -pub fn v8_shutdown() { - unsafe { - v8::V8::dispose(); - } - v8::V8::shutdown_platform(); -} - -pub fn v8_do(f: impl FnOnce()) { - static V8_INIT: Once = Once::new(); - V8_INIT.call_once(|| { - v8_init(); - }); - f(); - // v8_shutdown(); -} |