0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-10-31 09:14:20 -04:00
denoland-deno/serde_v8/src/ser.rs

706 lines
18 KiB
Rust
Raw Normal View History

// 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;
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 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> {
scope: ScopePtr<'a, 'b, 'c>,
ptr: Option<std::ptr::NonNull<u8>>,
len: Option<usize>,
}
impl<'a, 'b, 'c> MagicByteStringSerializer<'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 MagicByteStringSerializer<'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::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>(
&mut self,
key: &'static str,
value: &T,
) -> 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!(),
}
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())
};
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())
}
}
// 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>),
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 {
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);
Ok(StructSerializers::MagicByteString(m))
}
magic::u16string::NAME => {
let m = MagicU16StringSerializer::new(self.scope);
Ok(StructSerializers::MagicU16String(m))
}
_ => {
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))
}
}
// 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")
}