summaryrefslogtreecommitdiff
path: root/serde_v8/src/ser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'serde_v8/src/ser.rs')
-rw-r--r--serde_v8/src/ser.rs229
1 files changed, 39 insertions, 190 deletions
diff --git a/serde_v8/src/ser.rs b/serde_v8/src/ser.rs
index ce7e8c707..5241aeaef 100644
--- a/serde_v8/src/ser.rs
+++ b/serde_v8/src/ser.rs
@@ -6,7 +6,9 @@ use std::cell::RefCell;
use crate::error::{Error, Result};
use crate::keys::v8_struct_key;
-use crate::magic;
+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>>;
@@ -212,191 +214,55 @@ impl<'a, 'b, 'c> ser::SerializeStruct for ObjectSerializer<'a, 'b, 'c> {
}
}
-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())
- }
-}
-
-pub struct MagicByteStringSerializer<'a, 'b, 'c> {
+pub struct MagicalSerializer<'a, 'b, 'c, T> {
scope: ScopePtr<'a, 'b, 'c>,
- ptr: Option<std::ptr::NonNull<u8>>,
- len: Option<usize>,
+ opaque: u64,
+ p1: std::marker::PhantomData<T>,
}
-impl<'a, 'b, 'c> MagicByteStringSerializer<'a, 'b, 'c> {
- pub fn new(scope: ScopePtr<'a, 'b, 'c>) -> Self {
+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,
- ptr: None,
- len: None,
+ opaque: 0,
+ p1: std::marker::PhantomData::<T> {},
}
}
}
-impl<'a, 'b, 'c> ser::SerializeStruct
- for MagicByteStringSerializer<'a, 'b, 'c>
+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<T: ?Sized + Serialize>(
- &mut self,
- key: &'static str,
- value: &T,
- ) -> Result<()> {
- // Get u64 chunk
- let transmuted: u64 = value.serialize(magic::FieldSerializer {})?;
- match key {
- magic::bytestring::FIELD_PTR => {
- self.ptr = std::ptr::NonNull::new(transmuted as *mut u8);
- }
- magic::bytestring::FIELD_LEN => {
- self.len = Some(transmuted as usize);
- }
- _ => unreachable!(),
- }
- Ok(())
- }
-
- fn end(self) -> JsResult<'a> {
- // SAFETY: This function is only called from ByteString::serialize(), which
- // guarantees the Vec is still alive.
- let bytes = unsafe {
- std::slice::from_raw_parts(self.ptr.unwrap().as_ptr(), self.len.unwrap())
- };
- let scope = &mut *self.scope.borrow_mut();
- let v8_value =
- v8::String::new_from_one_byte(scope, bytes, v8::NewStringType::Normal)
- .unwrap();
- Ok(v8_value.into())
- }
-}
-
-pub struct MagicU16StringSerializer<'a, 'b, 'c> {
- scope: ScopePtr<'a, 'b, 'c>,
- ptr: Option<std::ptr::NonNull<u16>>,
- len: Option<usize>,
-}
-
-impl<'a, 'b, 'c> MagicU16StringSerializer<'a, 'b, 'c> {
- pub fn new(scope: ScopePtr<'a, 'b, 'c>) -> Self {
- Self {
- scope,
- ptr: None,
- len: None,
- }
- }
-}
-
-impl<'a, 'b, 'c> ser::SerializeStruct for MagicU16StringSerializer<'a, 'b, 'c> {
- type Ok = JsValue<'a>;
- type Error = Error;
-
- fn serialize_field<T: ?Sized + Serialize>(
+ fn serialize_field<U: ?Sized + Serialize>(
&mut self,
key: &'static str,
- value: &T,
+ value: &U,
) -> Result<()> {
- // Get u64 chunk
- let transmuted = value.serialize(magic::FieldSerializer {})?;
- match key {
- magic::u16string::FIELD_PTR => {
- self.ptr = std::ptr::NonNull::new(transmuted as *mut u16)
- }
- magic::u16string::FIELD_LEN => self.len = Some(transmuted as usize),
- _ => unreachable!(),
- }
+ 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: This function is only called from U16String::serialize(), which
- // guarantees the Vec is still alive.
- let slice = unsafe {
- std::slice::from_raw_parts(self.ptr.unwrap().as_ptr(), self.len.unwrap())
- };
+ // SAFETY: transerialization assumptions imply `T` is still alive.
+ let x: &T = unsafe { opaque_deref(self.opaque) };
let scope = &mut *self.scope.borrow_mut();
-
- let v8_value =
- v8::String::new_from_two_byte(scope, slice, v8::NewStringType::Normal)
- .unwrap();
- Ok(v8_value.into())
+ x.to_v8(scope)
}
}
// Dispatches between magic and regular struct serializers
pub enum StructSerializers<'a, 'b, 'c> {
- Magic(MagicSerializer<'a>),
- MagicBuffer(MagicBufferSerializer<'a, 'b, 'c>),
- MagicByteString(MagicByteStringSerializer<'a, 'b, 'c>),
- MagicU16String(MagicU16StringSerializer<'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>),
}
@@ -650,23 +516,24 @@ impl<'a, 'b, 'c> ser::Serializer for Serializer<'a, 'b, 'c> {
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))
- }
- magic::bytestring::NAME => {
- let m = MagicByteStringSerializer::new(self.scope);
+ ByteString::MAGIC_NAME => {
+ let m = MagicalSerializer::<ByteString>::new(self.scope);
Ok(StructSerializers::MagicByteString(m))
}
- magic::u16string::NAME => {
- let m = MagicU16StringSerializer::new(self.scope);
+ 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))
}
@@ -685,21 +552,3 @@ impl<'a, 'b, 'c> ser::Serializer for Serializer<'a, 'b, 'c> {
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")
-}