diff options
Diffstat (limited to 'serde_v8/src')
-rw-r--r-- | serde_v8/src/de.rs | 614 | ||||
-rw-r--r-- | serde_v8/src/error.rs | 48 | ||||
-rw-r--r-- | serde_v8/src/keys.rs | 31 | ||||
-rw-r--r-- | serde_v8/src/lib.rs | 20 | ||||
-rw-r--r-- | serde_v8/src/magic/buffer.rs | 119 | ||||
-rw-r--r-- | serde_v8/src/magic/bytestring.rs | 122 | ||||
-rw-r--r-- | serde_v8/src/magic/mod.rs | 9 | ||||
-rw-r--r-- | serde_v8/src/magic/string_or_buffer.rs | 45 | ||||
-rw-r--r-- | serde_v8/src/magic/transl8.rs | 143 | ||||
-rw-r--r-- | serde_v8/src/magic/u16string.rs | 83 | ||||
-rw-r--r-- | serde_v8/src/magic/value.rs | 48 | ||||
-rw-r--r-- | serde_v8/src/magic/zero_copy_buf.rs | 136 | ||||
-rw-r--r-- | serde_v8/src/payload.rs | 40 | ||||
-rw-r--r-- | serde_v8/src/ser.rs | 554 | ||||
-rw-r--r-- | serde_v8/src/serializable.rs | 142 | ||||
-rw-r--r-- | serde_v8/src/utils.rs | 33 |
16 files changed, 0 insertions, 2187 deletions
diff --git a/serde_v8/src/de.rs b/serde_v8/src/de.rs deleted file mode 100644 index 002b741cf..000000000 --- a/serde_v8/src/de.rs +++ /dev/null @@ -1,614 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. -use serde::de::{self, Visitor}; -use serde::Deserialize; - -use crate::error::{Error, Result}; -use crate::keys::{v8_struct_key, KeyCache}; -use crate::magic::transl8::FromV8; -use crate::magic::transl8::{visit_magic, MagicType}; -use crate::payload::ValueType; -use crate::{magic, Buffer, ByteString, U16String}; - -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!() - } - }; -} - -// TODO: maybe check for BigInt truncation ? -// (i.e: values larger than i64/u64 can hold) -macro_rules! deserialize_signed { - ($dmethod:ident, $vmethod:ident, $t:tt) => { - fn $dmethod<V>(self, visitor: V) -> Result<V::Value> - where - V: Visitor<'de>, - { - let value: $t = match self.input.is_big_int() { - true => { - let bigint = v8::Local::<v8::BigInt>::try_from(self.input); - bigint.unwrap().i64_value().0 as $t - } - false => self.input.integer_value(&mut self.scope).unwrap() as $t, - }; - visitor.$vmethod(value) - } - }; -} - -macro_rules! deserialize_unsigned { - ($dmethod:ident, $vmethod:ident, $t:tt) => { - fn $dmethod<V>(self, visitor: V) -> Result<V::Value> - where - V: Visitor<'de>, - { - let value: $t = match self.input.is_big_int() { - true => { - let bigint = v8::Local::<v8::BigInt>::try_from(self.input); - bigint.unwrap().u64_value().0 as $t - } - false => self.input.integer_value(&mut self.scope).unwrap() as $t, - }; - visitor.$vmethod(value) - } - }; -} - -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), - // Map to Vec<u8> when deserialized via deserialize_any - // e.g: for untagged enums or StringOrBuffer - ValueType::ArrayBufferView | ValueType::ArrayBuffer => { - magic::zero_copy_buf::ZeroCopyBuf::from_v8(&mut *self.scope, self.input) - .and_then(|zb| visitor.visit_byte_buf(Vec::from(&*zb))) - } - } - } - - 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()) - } - - // signed - 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); - // unsigned - deserialize_unsigned!(deserialize_u8, visit_u8, u8); - deserialize_unsigned!(deserialize_u16, visit_u16, u16); - deserialize_unsigned!(deserialize_u32, visit_u32, u32); - deserialize_unsigned!(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(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(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>, - { - visitor.visit_unit() - } - - 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) - .map_err(|_| Error::ExpectedObject)?; - 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>, - { - match name { - Buffer::MAGIC_NAME => { - visit_magic(visitor, Buffer::from_v8(self.scope, self.input)?) - } - ByteString::MAGIC_NAME => { - visit_magic(visitor, ByteString::from_v8(self.scope, self.input)?) - } - U16String::MAGIC_NAME => { - visit_magic(visitor, U16String::from_v8(self.scope, self.input)?) - } - magic::Value::MAGIC_NAME => { - visit_magic(visitor, magic::Value::from_v8(self.scope, self.input)?) - } - _ => { - // Regular struct - let obj = self.input.try_into().or(Err(Error::ExpectedObject))?; - visitor.visit_seq(StructAccess { - fields, - obj, - pos: 0, - scope: self.scope, - _cache: None, - }) - } - } - } - - /// 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 StructAccess<'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>, -} - -impl<'de> de::SeqAccess<'de> for StructAccess<'_, '_, '_> { - type Error = Error; - - fn next_element_seed<T: de::DeserializeSeed<'de>>( - &mut self, - seed: T, - ) -> Result<Option<T::Value>> { - if self.pos >= self.fields.len() { - return Ok(None); - } - - let pos = self.pos; - self.pos += 1; - - let field = self.fields[pos]; - let key = v8_struct_key(self.scope, field).into(); - let val = self.obj.get(self.scope, key).unwrap(); - let mut deserializer = Deserializer::new(self.scope, val, None); - match seed.deserialize(&mut deserializer) { - Ok(val) => Ok(Some(val)), - // Fallback to Ok(None) for #[serde(Default)] at cost of error quality ... - // TODO(@AaronO): double check that there's no better solution - Err(_) if val.is_undefined() => Ok(None), - Err(e) => Err(e), - } - } -} - -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 e4f7f363b..000000000 --- a/serde_v8/src/error.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2018-2022 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, - ExpectedArray, - ExpectedMap, - ExpectedEnum, - ExpectedObject, - ExpectedBuffer, - - ExpectedUtf8, - ExpectedLatin1, - - 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 4811a87f8..000000000 --- a/serde_v8/src/keys.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. -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 203e1d004..000000000 --- a/serde_v8/src/lib.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2018-2022 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::bytestring::ByteString; -pub use magic::string_or_buffer::StringOrBuffer; -pub use magic::u16string::U16String; -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 484984ac5..000000000 --- a/serde_v8/src/magic/buffer.rs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -use std::ops::Deref; -use std::ops::DerefMut; -use std::sync::Mutex; - -use super::transl8::FromV8; -use super::transl8::ToV8; -use super::zero_copy_buf::ZeroCopyBuf; -use crate::magic::transl8::impl_magic; - -// 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_magic!(MagicBuffer); - -impl MagicBuffer { - 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() - } -} - -impl ToV8 for MagicBuffer { - fn to_v8<'a>( - &self, - scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error> { - let buf: Box<[u8]> = match self { - Self::FromV8(buf) => { - let value: &[u8] = buf; - value.into() - } - Self::ToV8(x) => x.lock().unwrap().take().expect("MagicBuffer was empty"), - }; - - if buf.is_empty() { - let ab = v8::ArrayBuffer::new(scope, 0); - return Ok( - v8::Uint8Array::new(scope, ab, 0, 0) - .expect("Failed to create Uint8Array") - .into(), - ); - } - 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); - Ok( - v8::Uint8Array::new(scope, ab, 0, buf_len) - .expect("Failed to create Uint8Array") - .into(), - ) - } -} - -impl FromV8 for MagicBuffer { - fn from_v8( - scope: &mut v8::HandleScope, - value: v8::Local<v8::Value>, - ) -> Result<Self, crate::Error> { - Ok(Self::FromV8(ZeroCopyBuf::from_v8(scope, value)?)) - } -} diff --git a/serde_v8/src/magic/bytestring.rs b/serde_v8/src/magic/bytestring.rs deleted file mode 100644 index 43ac54b97..000000000 --- a/serde_v8/src/magic/bytestring.rs +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -use std::ops::{Deref, DerefMut}; - -use super::transl8::{FromV8, ToV8}; -use crate::magic::transl8::impl_magic; -use crate::Error; - -#[derive(PartialEq, Eq, Clone, Debug)] -pub struct ByteString(pub Vec<u8>); -impl_magic!(ByteString); - -impl ByteString { - pub fn new() -> ByteString { - ByteString(Vec::new()) - } - - pub fn with_capacity(capacity: usize) -> ByteString { - ByteString(Vec::with_capacity(capacity)) - } - - pub fn capacity(&self) -> usize { - self.0.capacity() - } - - pub fn reserve(&mut self, additional: usize) { - self.0.reserve(additional) - } - - pub fn reserve_exact(&mut self, additional: usize) { - self.0.reserve_exact(additional) - } - - pub fn shrink_to_fit(&mut self) { - self.0.shrink_to_fit() - } - - pub fn truncate(&mut self, len: usize) { - self.0.truncate(len) - } - - pub fn push(&mut self, value: u8) { - self.0.push(value) - } - - pub fn pop(&mut self) -> Option<u8> { - self.0.pop() - } -} - -impl Default for ByteString { - fn default() -> Self { - ByteString::new() - } -} - -impl Deref for ByteString { - type Target = [u8]; - - fn deref(&self) -> &[u8] { - self.0.deref() - } -} - -impl DerefMut for ByteString { - fn deref_mut(&mut self) -> &mut [u8] { - self.0.deref_mut() - } -} - -impl AsRef<[u8]> for ByteString { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } -} - -impl AsMut<[u8]> for ByteString { - fn as_mut(&mut self) -> &mut [u8] { - self.0.as_mut() - } -} - -impl ToV8 for ByteString { - fn to_v8<'a>( - &self, - scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error> { - let v = - v8::String::new_from_one_byte(scope, self, v8::NewStringType::Normal) - .unwrap(); - Ok(v.into()) - } -} - -impl FromV8 for ByteString { - fn from_v8( - scope: &mut v8::HandleScope, - value: v8::Local<v8::Value>, - ) -> Result<Self, crate::Error> { - let v8str = v8::Local::<v8::String>::try_from(value) - .map_err(|_| Error::ExpectedString)?; - if !v8str.contains_only_onebyte() { - return Err(Error::ExpectedLatin1); - } - let len = v8str.length(); - let mut buffer = Vec::with_capacity(len); - // SAFETY: we set length == capacity (see previous line), - // before immediately writing into that buffer and sanity check with an assert - #[allow(clippy::uninit_vec)] - unsafe { - buffer.set_len(len); - let written = v8str.write_one_byte( - scope, - &mut buffer, - 0, - v8::WriteOptions::NO_NULL_TERMINATION, - ); - assert!(written == len); - } - Ok(ByteString(buffer)) - } -} diff --git a/serde_v8/src/magic/mod.rs b/serde_v8/src/magic/mod.rs deleted file mode 100644 index bc86c6a7c..000000000 --- a/serde_v8/src/magic/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. -pub mod buffer; -pub mod bytestring; -pub mod string_or_buffer; -pub mod transl8; -pub mod u16string; -mod value; -pub mod zero_copy_buf; -pub use value::Value; diff --git a/serde_v8/src/magic/string_or_buffer.rs b/serde_v8/src/magic/string_or_buffer.rs deleted file mode 100644 index edde2adcd..000000000 --- a/serde_v8/src/magic/string_or_buffer.rs +++ /dev/null @@ -1,45 +0,0 @@ -use std::ops::Deref; - -#[derive(Debug)] -pub struct StringOrBuffer(Vec<u8>); - -impl Deref for StringOrBuffer { - type Target = Vec<u8>; - fn deref(&self) -> &Vec<u8> { - &self.0 - } -} - -impl StringOrBuffer { - pub fn into_bytes(self) -> Vec<u8> { - self.0 - } -} - -impl<'de> serde::Deserialize<'de> for StringOrBuffer { - fn deserialize<D>(deserializer: D) -> Result<StringOrBuffer, D::Error> - where - D: serde::Deserializer<'de>, - { - StringOrBufferInner::deserialize(deserializer) - .map(|x| StringOrBuffer(x.into_bytes())) - } -} - -// TODO(@AaronO): explore if we can make this work with ZeroCopyBuf -#[derive(serde::Deserialize)] -#[serde(untagged)] -enum StringOrBufferInner { - #[serde(with = "serde_bytes")] - Buffer(Vec<u8>), - String(String), -} - -impl StringOrBufferInner { - fn into_bytes(self) -> Vec<u8> { - match self { - Self::String(s) => s.into_bytes(), - Self::Buffer(b) => b, - } - } -} diff --git a/serde_v8/src/magic/transl8.rs b/serde_v8/src/magic/transl8.rs deleted file mode 100644 index 458b82129..000000000 --- a/serde_v8/src/magic/transl8.rs +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -//! Transerialization extends the set of serde-compatible types (for given de/serializers). -//! By "hackishly" transmuting references across serde boundaries as u64s. -//! Type-safety is enforced using special struct names for each "magic type". -//! Memory-safety relies on transerialized values being "pinned" during de/serialization. - -pub(crate) const MAGIC_FIELD: &str = "$__v8_magic_field"; - -pub(crate) trait MagicType { - const NAME: &'static str; - const MAGIC_NAME: &'static str; -} - -pub(crate) trait ToV8 { - fn to_v8<'a>( - &self, - scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error>; -} - -pub(crate) trait FromV8: Sized { - fn from_v8( - scope: &mut v8::HandleScope, - value: v8::Local<v8::Value>, - ) -> Result<Self, crate::Error>; -} - -pub(crate) fn magic_serialize<T, S>( - serializer: S, - x: &T, -) -> Result<S::Ok, S::Error> -where - S: serde::Serializer, - T: MagicType, -{ - use serde::ser::SerializeStruct; - - let mut s = serializer.serialize_struct(T::MAGIC_NAME, 1)?; - let ptr = opaque_send(x); - s.serialize_field(MAGIC_FIELD, &ptr)?; - s.end() -} - -pub(crate) fn magic_deserialize<'de, T, D>( - deserializer: D, -) -> Result<T, D::Error> -where - D: serde::Deserializer<'de>, - T: MagicType, -{ - struct ValueVisitor<T> { - p1: std::marker::PhantomData<T>, - } - - impl<'de, T: MagicType> serde::de::Visitor<'de> for ValueVisitor<T> { - type Value = T; - - fn expecting( - &self, - formatter: &mut std::fmt::Formatter, - ) -> std::fmt::Result { - formatter.write_str("a ")?; - formatter.write_str(T::NAME) - } - - fn visit_u64<E>(self, ptr: u64) -> Result<Self::Value, E> - where - E: serde::de::Error, - { - // SAFETY: opaque ptr originates from visit_magic, which forgets ownership so we can take it - Ok(unsafe { opaque_take(ptr) }) - } - } - - deserializer.deserialize_struct( - T::MAGIC_NAME, - &[MAGIC_FIELD], - ValueVisitor::<T> { - p1: std::marker::PhantomData, - }, - ) -} - -pub(crate) fn visit_magic<'de, T, V, E>(visitor: V, x: T) -> Result<V::Value, E> -where - V: serde::de::Visitor<'de>, - E: serde::de::Error, -{ - let y = visitor.visit_u64::<E>(opaque_send(&x)); - std::mem::forget(x); - y -} - -/// Constructs an "opaque" ptr from a reference to transerialize -pub(crate) fn opaque_send<T: Sized>(x: &T) -> u64 { - (x as *const T) as u64 -} - -/// Copies an "opaque" ptr from a reference to an opaque ptr (transerialized) -/// NOTE: ptr-to-ptr, extra indirection -pub(crate) unsafe fn opaque_recv<T: ?Sized>(ptr: &T) -> u64 { - *(ptr as *const T as *const u64) -} - -/// Transmutes an "opaque" ptr back into a reference -pub(crate) unsafe fn opaque_deref<'a, T>(ptr: u64) -> &'a T { - std::mem::transmute(ptr) -} - -/// Transmutes & copies the value from the "opaque" ptr -/// NOTE: takes ownership & requires other end to forget its ownership -pub(crate) unsafe fn opaque_take<T>(ptr: u64) -> T { - std::mem::transmute_copy::<T, T>(std::mem::transmute(ptr)) -} - -macro_rules! impl_magic { - ($t:ty) => { - impl crate::magic::transl8::MagicType for $t { - const NAME: &'static str = stringify!($t); - const MAGIC_NAME: &'static str = concat!("$__v8_magic_", stringify!($t)); - } - - impl serde::Serialize for $t { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: serde::Serializer, - { - crate::magic::transl8::magic_serialize(serializer, self) - } - } - - impl<'de> serde::Deserialize<'de> for $t { - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where - D: serde::Deserializer<'de>, - { - crate::magic::transl8::magic_deserialize(deserializer) - } - } - }; -} -pub(crate) use impl_magic; diff --git a/serde_v8/src/magic/u16string.rs b/serde_v8/src/magic/u16string.rs deleted file mode 100644 index 39ebf88d9..000000000 --- a/serde_v8/src/magic/u16string.rs +++ /dev/null @@ -1,83 +0,0 @@ -use crate::magic::transl8::impl_magic; -use crate::Error; -use std::ops::{Deref, DerefMut}; - -use super::transl8::{FromV8, ToV8}; - -#[derive(Default, PartialEq, Eq, Debug)] -pub struct U16String(pub Vec<u16>); -impl_magic!(U16String); - -impl U16String { - pub fn with_zeroes(length: usize) -> U16String { - U16String(vec![0u16; length]) - } - - pub fn truncate(&mut self, new_length: usize) { - self.0.truncate(new_length); - self.0.shrink_to_fit() - } -} - -impl Deref for U16String { - type Target = [u16]; - fn deref(&self) -> &[u16] { - self.0.deref() - } -} - -impl DerefMut for U16String { - fn deref_mut(&mut self) -> &mut [u16] { - self.0.deref_mut() - } -} - -impl AsRef<[u16]> for U16String { - fn as_ref(&self) -> &[u16] { - self.0.as_ref() - } -} - -impl AsMut<[u16]> for U16String { - fn as_mut(&mut self) -> &mut [u16] { - self.0.as_mut() - } -} - -impl ToV8 for U16String { - fn to_v8<'a>( - &self, - scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error> { - let v = - v8::String::new_from_two_byte(scope, self, v8::NewStringType::Normal) - .unwrap(); - Ok(v.into()) - } -} - -impl FromV8 for U16String { - fn from_v8( - scope: &mut v8::HandleScope, - value: v8::Local<v8::Value>, - ) -> Result<Self, crate::Error> { - let v8str = v8::Local::<v8::String>::try_from(value) - .map_err(|_| Error::ExpectedString)?; - let len = v8str.length(); - let mut buffer = Vec::with_capacity(len); - // SAFETY: we set length == capacity (see previous line), - // before immediately writing into that buffer and sanity check with an assert - #[allow(clippy::uninit_vec)] - unsafe { - buffer.set_len(len); - let written = v8str.write( - scope, - &mut buffer, - 0, - v8::WriteOptions::NO_NULL_TERMINATION, - ); - assert!(written == len); - } - Ok(U16String(buffer)) - } -} diff --git a/serde_v8/src/magic/value.rs b/serde_v8/src/magic/value.rs deleted file mode 100644 index 5d844fbda..000000000 --- a/serde_v8/src/magic/value.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -use crate::magic::transl8::impl_magic; -use crate::magic::transl8::FromV8; -use crate::magic::transl8::ToV8; -use std::mem::transmute; - -/// serde_v8::Value allows passing through `v8::Value`s untouched -/// when de/serializing & allows mixing rust & v8 values in structs, tuples... -// -// SAFETY: caveat emptor, the rust-compiler can no longer link lifetimes to their -// original scope, you must take special care in ensuring your handles don't outlive their scope -pub struct Value<'s> { - pub v8_value: v8::Local<'s, v8::Value>, -} -impl_magic!(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 ToV8 for Value<'_> { - fn to_v8<'a>( - &self, - _scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error> { - // SAFETY: not fully safe, since lifetimes are detached from original scope - Ok(unsafe { transmute(self.v8_value) }) - } -} - -impl FromV8 for Value<'_> { - fn from_v8( - _scope: &mut v8::HandleScope, - value: v8::Local<v8::Value>, - ) -> Result<Self, crate::Error> { - // SAFETY: not fully safe, since lifetimes are detached from original scope - Ok(unsafe { transmute::<Value, Value>(value.into()) }) - } -} 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 c63d4ba66..000000000 --- a/serde_v8/src/magic/zero_copy_buf.rs +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -use std::cell::Cell; -use std::ops::Deref; -use std::ops::DerefMut; - -use super::transl8::FromV8; - -/// 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 from_buffer( - buffer: v8::Local<v8::ArrayBuffer>, - byte_offset: usize, - byte_length: usize, - ) -> Result<Self, v8::DataError> { - let backing_store = buffer.get_backing_store(); - match backing_store.is_shared() { - true => Err(v8::DataError::BadType { - actual: "shared ArrayBufferView", - expected: "non-shared ArrayBufferView", - }), - false => Ok(Self { - backing_store, - byte_offset, - byte_length, - }), - } - } - - pub fn from_view( - scope: &mut v8::HandleScope, - view: v8::Local<v8::ArrayBufferView>, - ) -> Result<Self, v8::DataError> { - let buffer = view.buffer(scope).ok_or(v8::DataError::NoData { - expected: "view to have a buffer", - })?; - Self::from_buffer(buffer, view.byte_offset(), view.byte_length()) - } -} - -impl FromV8 for ZeroCopyBuf { - fn from_v8( - scope: &mut v8::HandleScope, - value: v8::Local<v8::Value>, - ) -> Result<Self, crate::Error> { - if value.is_array_buffer() { - value - .try_into() - .and_then(|b| Self::from_buffer(b, 0, b.byte_length())) - } else { - value - .try_into() - .and_then(|view| Self::from_view(scope, view)) - } - .map_err(|_| crate::Error::ExpectedBuffer) - } -} - -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 c9f3e85aa..000000000 --- a/serde_v8/src/payload.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -// TODO: maybe add a Payload type that holds scope & v8::Value -// so it can implement Deserialize by itself - -// Classifies v8::Values into sub-types -#[derive(Debug)] -pub enum ValueType { - Null, - Bool, - Number, - String, - Array, - ArrayBuffer, - ArrayBufferView, - 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_array_buffer() { - return Self::ArrayBuffer; - } else if v.is_array_buffer_view() { - return Self::ArrayBufferView; - } 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 5241aeaef..000000000 --- a/serde_v8/src/ser.rs +++ /dev/null @@ -1,554 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. -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::transl8::MAGIC_FIELD; -use crate::magic::transl8::{opaque_deref, opaque_recv, MagicType, ToV8}; -use crate::{magic, Buffer, ByteString, U16String}; - -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 null = v8::null(scope).into(); - let key = v8_struct_key(scope, self.variant).into(); - let obj = - v8::Object::with_prototype_and_properties(scope, null, &[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>, - keys: Vec<v8::Local<'a, v8::Name>>, - values: Vec<JsValue<'a>>, -} - -impl<'a, 'b, 'c> ObjectSerializer<'a, 'b, 'c> { - pub fn new(scope: ScopePtr<'a, 'b, 'c>, len: usize) -> Self { - let keys = Vec::with_capacity(len); - let values = Vec::with_capacity(len); - Self { - scope, - keys, - values, - } - } -} - -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.keys.push(key); - self.values.push(value); - Ok(()) - } - - fn end(self) -> JsResult<'a> { - let scope = &mut *self.scope.borrow_mut(); - let null = v8::null(scope); - let obj = v8::Object::with_prototype_and_properties( - scope, - null.into(), - &self.keys[..], - &self.values[..], - ); - Ok(obj.into()) - } -} - -pub struct MagicalSerializer<'a, 'b, 'c, T> { - scope: ScopePtr<'a, 'b, 'c>, - opaque: u64, - p1: std::marker::PhantomData<T>, -} - -impl<'a, 'b, 'c, T> MagicalSerializer<'a, 'b, 'c, T> { - pub fn new(scope: ScopePtr<'a, 'b, 'c>) -> MagicalSerializer<'a, 'b, 'c, T> { - Self { - scope, - opaque: 0, - p1: std::marker::PhantomData::<T> {}, - } - } -} - -impl<'a, 'b, 'c, T: MagicType + ToV8> ser::SerializeStruct - for MagicalSerializer<'a, 'b, 'c, T> -{ - type Ok = JsValue<'a>; - type Error = Error; - - fn serialize_field<U: ?Sized + Serialize>( - &mut self, - key: &'static str, - value: &U, - ) -> Result<()> { - assert_eq!(key, MAGIC_FIELD); - let ptr: &U = value; - // SAFETY: MagicalSerializer only ever receives single field u64s, - // type-safety is ensured by MAGIC_NAME checks in `serialize_struct()` - self.opaque = unsafe { opaque_recv(ptr) }; - Ok(()) - } - - fn end(self) -> JsResult<'a> { - // SAFETY: transerialization assumptions imply `T` is still alive. - let x: &T = unsafe { opaque_deref(self.opaque) }; - let scope = &mut *self.scope.borrow_mut(); - x.to_v8(scope) - } -} - -// Dispatches between magic and regular struct serializers -pub enum StructSerializers<'a, 'b, 'c> { - Magic(MagicalSerializer<'a, 'b, 'c, magic::Value<'a>>), - MagicBuffer(MagicalSerializer<'a, 'b, 'c, Buffer>), - MagicByteString(MagicalSerializer<'a, 'b, 'c, ByteString>), - MagicU16String(MagicalSerializer<'a, 'b, 'c, U16String>), - 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::MagicByteString(s) => s.serialize_field(key, value), - StructSerializers::MagicU16String(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::MagicByteString(s) => s.end(), - StructSerializers::MagicU16String(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>, - keys: Vec<v8::Local<'a, v8::Name>>, - values: Vec<JsValue<'a>>, -} - -impl<'a, 'b, 'c> MapSerializer<'a, 'b, 'c> { - pub fn new(scope: ScopePtr<'a, 'b, 'c>, len: Option<usize>) -> Self { - let keys = Vec::with_capacity(len.unwrap_or_default()); - let values = Vec::with_capacity(len.unwrap_or_default()); - Self { - scope, - keys, - values, - } - } -} - -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<()> { - let key = key.serialize(Serializer::new(self.scope))?; - self.keys.push(key.try_into().map_err(|_| { - Error::Message("Serialized Maps expect String keys".into()) - })?); - Ok(()) - } - - fn serialize_value<T: ?Sized + Serialize>( - &mut self, - value: &T, - ) -> Result<()> { - let v8_value = value.serialize(Serializer::new(self.scope))?; - self.values.push(v8_value); - Ok(()) - } - - fn end(self) -> JsResult<'a> { - debug_assert!(self.keys.len() == self.values.len()); - let scope = &mut *self.scope.borrow_mut(); - let null = v8::null(scope).into(); - let obj = v8::Object::with_prototype_and_properties( - scope, - null, - &self.keys[..], - &self.values[..], - ); - Ok(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, len)) - } - - /// Serialises Rust typed structs into plain JS objects. - fn serialize_struct( - self, - name: &'static str, - len: usize, - ) -> Result<Self::SerializeStruct> { - match name { - ByteString::MAGIC_NAME => { - let m = MagicalSerializer::<ByteString>::new(self.scope); - Ok(StructSerializers::MagicByteString(m)) - } - U16String::MAGIC_NAME => { - let m = MagicalSerializer::<U16String>::new(self.scope); - Ok(StructSerializers::MagicU16String(m)) - } - Buffer::MAGIC_NAME => { - let m = MagicalSerializer::<Buffer>::new(self.scope); - Ok(StructSerializers::MagicBuffer(m)) - } - magic::Value::MAGIC_NAME => { - let m = MagicalSerializer::<magic::Value<'a>>::new(self.scope); - Ok(StructSerializers::Magic(m)) - } - _ => { - // Regular structs - let o = ObjectSerializer::new(self.scope, len); - 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)) - } -} diff --git a/serde_v8/src/serializable.rs b/serde_v8/src/serializable.rs deleted file mode 100644 index 533b3f83f..000000000 --- a/serde_v8/src/serializable.rs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. -use std::any::TypeId; -use std::mem::transmute_copy; - -use crate::Buffer; -use crate::ByteString; -use crate::U16String; - -/// 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 -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), - String(String), - Buffer(Buffer), - ByteString(ByteString), - U16String(U16String), -} - -impl serde::Serialize for Primitive { - fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error> - where - S: serde::Serializer, - { - match self { - Self::Unit => ().serialize(s), - Self::Bool(x) => x.serialize(s), - Self::Int8(x) => x.serialize(s), - Self::Int16(x) => x.serialize(s), - Self::Int32(x) => x.serialize(s), - Self::Int64(x) => x.serialize(s), - Self::UInt8(x) => x.serialize(s), - Self::UInt16(x) => x.serialize(s), - Self::UInt32(x) => x.serialize(s), - Self::UInt64(x) => x.serialize(s), - Self::Float32(x) => x.serialize(s), - Self::Float64(x) => x.serialize(s), - Self::String(x) => x.serialize(s), - Self::Buffer(x) => x.serialize(s), - Self::ByteString(x) => x.serialize(s), - Self::U16String(x) => x.serialize(s), - } - } -} - -impl<T: serde::Serialize + 'static> From<T> for SerializablePkg { - fn from(x: T) -> Self { - #[inline(always)] - fn tc<T, U>(src: T) -> U { - let x = unsafe { transmute_copy(&src) }; - std::mem::forget(src); - x - } - - let tid = TypeId::of::<T>(); - if tid == TypeId::of::<()>() { - Self::Primitive(Primitive::Unit) - } else if tid == TypeId::of::<bool>() { - Self::Primitive(Primitive::Bool(tc(x))) - } else if tid == TypeId::of::<i8>() { - Self::Primitive(Primitive::Int8(tc(x))) - } else if tid == TypeId::of::<i16>() { - Self::Primitive(Primitive::Int16(tc(x))) - } else if tid == TypeId::of::<i32>() { - Self::Primitive(Primitive::Int32(tc(x))) - } else if tid == TypeId::of::<i64>() { - Self::Primitive(Primitive::Int64(tc(x))) - } else if tid == TypeId::of::<u8>() { - Self::Primitive(Primitive::UInt8(tc(x))) - } else if tid == TypeId::of::<u16>() { - Self::Primitive(Primitive::UInt16(tc(x))) - } else if tid == TypeId::of::<u32>() { - Self::Primitive(Primitive::UInt32(tc(x))) - } else if tid == TypeId::of::<u64>() { - Self::Primitive(Primitive::UInt64(tc(x))) - } else if tid == TypeId::of::<f32>() { - Self::Primitive(Primitive::Float32(tc(x))) - } else if tid == TypeId::of::<f64>() { - Self::Primitive(Primitive::Float64(tc(x))) - } else if tid == TypeId::of::<String>() { - Self::Primitive(Primitive::String(tc(x))) - } else if tid == TypeId::of::<Buffer>() { - Self::Primitive(Primitive::Buffer(tc(x))) - } else if tid == TypeId::of::<ByteString>() { - Self::Primitive(Primitive::ByteString(tc(x))) - } else if tid == TypeId::of::<U16String>() { - Self::Primitive(Primitive::U16String(tc(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 427ac5f2f..000000000 --- a/serde_v8/src/utils.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. -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(0, false).make_shared(); - v8::V8::initialize_platform(platform); - v8::V8::initialize(); -} - -pub fn v8_shutdown() { - unsafe { - v8::V8::dispose(); - } - v8::V8::dispose_platform(); -} - -pub fn v8_do(f: impl FnOnce()) { - static V8_INIT: Once = Once::new(); - V8_INIT.call_once(|| { - v8_init(); - }); - f(); - // v8_shutdown(); -} |