diff options
Diffstat (limited to 'serde_v8/src/magic')
-rw-r--r-- | serde_v8/src/magic/field.rs | 143 | ||||
-rw-r--r-- | serde_v8/src/magic/mod.rs | 5 | ||||
-rw-r--r-- | serde_v8/src/magic/value.rs | 79 |
3 files changed, 227 insertions, 0 deletions
diff --git a/serde_v8/src/magic/field.rs b/serde_v8/src/magic/field.rs new file mode 100644 index 000000000..20a387d43 --- /dev/null +++ b/serde_v8/src/magic/field.rs @@ -0,0 +1,143 @@ +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 new file mode 100644 index 000000000..c34847031 --- /dev/null +++ b/serde_v8/src/magic/mod.rs @@ -0,0 +1,5 @@ +mod field; +mod value; + +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 new file mode 100644 index 000000000..2cb622466 --- /dev/null +++ b/serde_v8/src/magic/value.rs @@ -0,0 +1,79 @@ +// 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) + } +} |