use alloc::boxed::Box;
use core::convert::Infallible;
#[cfg(feature = "std")]
use std::io;
use serde_core::{
Serialize, Serializer,
ser::{Impossible, SerializeSeq, SerializeStruct}
};
use super::{Error, SMI_MAX, SMI_MIN, SerializationTag};
use crate::{
ArrayBufferViewTag,
segmented_buf::{GrowStrategy, SegmentedBuf},
types
};
fn bigint_byte_length(n: i128) -> u32 {
let unsigned = if n < 0 { -n } else { n };
let byte_length = ((i128::BITS - unsigned.leading_zeros()) as u32 + 7) >> 3;
(byte_length + 7) & !7
}
fn bigint_bitfield(n: i128) -> u32 {
(if n < 0 { 1 } else { 0 }) | (bigint_byte_length(n) << 1)
}
#[derive(Debug, Clone)]
pub struct SerializeOptions {
pub version: u8,
pub unit_is_undefined: bool,
pub grow_strategy: GrowStrategy
}
impl Default for SerializeOptions {
fn default() -> Self {
Self {
version: 15,
unit_is_undefined: false,
grow_strategy: GrowStrategy::Linear { size: 256 }
}
}
}
pub(crate) trait Write
where
Error: From<Self::Error>
{
type Error;
fn push(&mut self, byte: u8) -> Result<(), Self::Error>;
fn extend(&mut self, bytes: &[u8]) -> Result<(), Self::Error>;
fn take_from(&mut self, buf: SegmentedBuf) -> Result<(), Self::Error>;
}
impl Write for SegmentedBuf {
type Error = Infallible;
#[inline]
fn push(&mut self, byte: u8) -> Result<(), Infallible> {
self.push(byte);
Ok(())
}
#[inline]
fn extend(&mut self, bytes: &[u8]) -> Result<(), Infallible> {
self.extend_from_slice(bytes);
Ok(())
}
#[inline]
fn take_from(&mut self, buf: SegmentedBuf) -> Result<(), Infallible> {
self.take_from(buf);
Ok(())
}
}
#[cfg(feature = "std")]
impl<W: io::Write> Write for W {
type Error = io::Error;
#[inline]
fn push(&mut self, byte: u8) -> io::Result<()> {
self.write_all(&[byte])
}
#[inline]
fn extend(&mut self, bytes: &[u8]) -> io::Result<()> {
self.write_all(bytes)
}
#[inline]
fn take_from(&mut self, buf: SegmentedBuf) -> io::Result<()> {
for segment in buf.segments() {
self.write_all(segment)?;
}
Ok(())
}
}
pub(crate) struct V8Serializer<W: Write>
where
Error: From<W::Error>
{
pub(crate) writer: W,
pub(crate) options: SerializeOptions
}
impl<W: Write> V8Serializer<W>
where
Error: From<W::Error>
{
pub fn new(writer: W, options: SerializeOptions) -> Self {
Self { writer, options }
}
pub fn write_header(&mut self) -> Result<(), Error> {
self.writer.push(SerializationTag::Version as u8)?;
if !(13..=16).contains(&self.options.version) {
return Err(Error::BadVersion(self.options.version));
}
self.write_var_int(self.options.version as _)?;
Ok(())
}
pub(crate) fn write_var_int(&mut self, mut value: u32) -> Result<(), W::Error> {
loop {
let byte = (value & 0x7F) as u8 | 0x80;
value >>= 7;
if value == 0 {
self.writer.push(byte & 0x7F)?;
break;
} else {
self.writer.push(byte)?;
}
}
Ok(())
}
pub(crate) fn write_var_int64(&mut self, mut value: u64) -> Result<(), W::Error> {
loop {
let byte = (value & 0x7F) as u8 | 0x80;
value >>= 7;
if value == 0 {
self.writer.push(byte & 0x7F)?;
break;
} else {
self.writer.push(byte)?;
}
}
Ok(())
}
pub(crate) fn write_zigzag(&mut self, value: i32) -> Result<(), W::Error> {
let unsigned = (value << 1) ^ (value >> 31);
self.write_var_int(unsigned as u32)
}
pub(crate) fn write_bigint_contents(&mut self, value: i128) -> Result<(), W::Error> {
self.write_var_int(bigint_bitfield(value))?;
let unsigned = (if value < 0 { -value } else { value }) as u128;
if unsigned < u64::MAX as u128 {
self.writer.extend(&(unsigned as u64).to_le_bytes())?;
} else {
self.writer.extend(&unsigned.to_le_bytes())?;
}
Ok(())
}
pub(crate) fn write_number(&mut self, num: i64, signed: bool) -> Result<(), W::Error> {
if signed && (SMI_MIN..=SMI_MAX).contains(&num) {
self.writer.push(SerializationTag::Int32 as u8)?;
self.write_zigzag(num as _)
} else {
self.writer.push(SerializationTag::Double as u8)?;
self.writer.extend(&(if signed { num as f64 } else { num as u64 as f64 }).to_le_bytes())?;
Ok(())
}
}
}
impl<'a, W: Write> serde_core::Serializer for &'a mut V8Serializer<W>
where
Error: From<W::Error>
{
type Ok = ();
type Error = Error;
type SerializeSeq = SeqSerializer<'a, W>;
type SerializeTuple = SeqSerializer<'a, W>;
type SerializeTupleStruct = SeqSerializer<'a, W>;
type SerializeMap = MapSerializer<'a, W>;
type SerializeStruct = StructSerializer<'a, W>;
type SerializeStructVariant = StructSerializer<'a, W>;
type SerializeTupleVariant = SeqSerializer<'a, W>;
fn is_human_readable(&self) -> bool {
false
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
self.writer.push(SerializationTag::BeginDenseJSArray as u8)?;
Ok(SeqSerializer {
subser: V8Serializer::<SegmentedBuf>::new(SegmentedBuf::new(self.options.grow_strategy.clone()), self.options.clone()),
ser: self,
len: 0
})
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeTupleStruct, Self::Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize
) -> Result<Self::SerializeTupleVariant, Self::Error> {
self.writer.push(SerializationTag::BeginJSObject as u8)?;
variant.serialize(&mut *self)?;
self.serialize_seq(Some(len))
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
self.writer.push(SerializationTag::BeginJSMap as u8)?;
Ok(MapSerializer { ser: self, entries: 0 })
}
fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct, Self::Error> {
self.writer.push(SerializationTag::BeginJSObject as u8)?;
Ok(StructSerializer { ser: self, len: 0 })
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
_len: usize
) -> Result<Self::SerializeStructVariant, Self::Error> {
self.writer.push(SerializationTag::BeginJSObject as u8)?;
variant.serialize(&mut *self)?;
self.serialize_struct(_name, _len)
}
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
self.writer.push(if v { SerializationTag::True } else { SerializationTag::False } as u8)?;
Ok(())
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
self.writer.push(SerializationTag::Null as u8)?;
Ok(())
}
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize
{
value.serialize(self)
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
self.writer.push(if !self.options.unit_is_undefined {
SerializationTag::Null
} else {
SerializationTag::Undefined
} as u8)?;
Ok(())
}
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
self.writer.push(SerializationTag::Utf8String as u8)?;
self.write_var_int(v.len() as _)?;
self.writer.extend(v.as_bytes())?;
Ok(())
}
fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
self.writer.push(SerializationTag::Utf8String as u8)?;
self.write_var_int(v.len_utf8() as _)?;
let mut x = [0; 4];
self.writer.extend(v.encode_utf8(&mut x).as_bytes())?;
Ok(())
}
fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize
{
match name {
types::set::SET_MAGIC => value.serialize(types::set::SetSerializer { ser: self }),
types::object::OBJECT_MAGIC => value.serialize(types::object::ObjectSerializer { ser: self }),
types::date::DATE_MAGIC => {
let value = value.serialize(DateExtractor)?;
self.writer.push(SerializationTag::Date as u8)?;
self.writer.extend(&value.to_le_bytes())?;
Ok(())
}
_ => value.serialize(self)
}
}
fn serialize_newtype_variant<T>(self, _name: &'static str, _variant_index: u32, variant: &'static str, value: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize
{
self.writer.push(SerializationTag::BeginJSObject as u8)?;
variant.serialize(&mut *self)?;
value.serialize(&mut *self)?;
self.writer.push(SerializationTag::EndJSObject as u8)?;
self.writer.push(1)?;
Ok(())
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
self.serialize_unit()
}
fn serialize_unit_variant(self, _name: &'static str, _variant_index: u32, variant: &'static str) -> Result<Self::Ok, Self::Error> {
self.serialize_str(variant)
}
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
if v.len() > u32::MAX as usize && self.options.version < 16 {
return Err(Error::BytesTooBig);
}
self.writer.push(SerializationTag::ArrayBuffer as u8)?;
self.write_var_int64(v.len() as _)?;
self.writer.extend(v)?;
self.writer.push(SerializationTag::ArrayBufferView as u8)?;
self.writer.push(ArrayBufferViewTag::Uint8Array as u8)?;
self.writer.push(0)?; self.write_var_int64(v.len() as _)?;
if self.options.version >= 14 {
self.writer.push(0)?; }
Ok(())
}
fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
self.writer.push(SerializationTag::Double as u8)?;
self.writer.extend(&(v as f64).to_le_bytes())?;
Ok(())
}
fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
self.writer.push(SerializationTag::Double as u8)?;
self.writer.extend(&v.to_le_bytes())?;
Ok(())
}
fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
self.writer.push(SerializationTag::Int32 as u8)?;
self.write_zigzag(v as _)?;
Ok(())
}
fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
self.writer.push(SerializationTag::Int32 as u8)?;
self.write_zigzag(v as _)?;
Ok(())
}
fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
self.writer.push(SerializationTag::Int32 as u8)?;
self.write_zigzag(v as _)?;
Ok(())
}
fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
self.writer.push(SerializationTag::Int32 as u8)?;
self.write_zigzag(v as _)?;
Ok(())
}
fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
self.write_number(v as _, true)?;
Ok(())
}
fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
self.write_number(v as _, false)?;
Ok(())
}
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
self.write_number(v as _, true)?;
Ok(())
}
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
self.write_number(v as _, false)?;
Ok(())
}
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
self.writer.push(SerializationTag::BigInt as u8)?;
self.write_bigint_contents(v)?;
Ok(())
}
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
self.writer.push(SerializationTag::BigInt as u8)?;
self.write_bigint_contents(v as _)?;
Ok(())
}
}
pub(crate) struct SeqSerializer<'a, W: Write>
where
Error: From<W::Error>
{
ser: &'a mut V8Serializer<W>,
subser: V8Serializer<SegmentedBuf>,
len: usize
}
impl<'a, W: Write> serde_core::ser::SerializeSeq for SeqSerializer<'a, W>
where
Error: From<W::Error>
{
type Ok = ();
type Error = Error;
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + serde_core::Serialize
{
value.serialize(&mut self.subser)?;
self.len += 1;
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
self.ser.write_var_int(self.len as _)?;
self.ser.writer.take_from(self.subser.writer)?;
self.ser.writer.push(SerializationTag::EndDenseJSArray as _)?;
self.ser.writer.push(0)?; self.ser.write_var_int(self.len as _)?;
Ok(())
}
}
impl<'a, W: Write> serde_core::ser::SerializeTuple for SeqSerializer<'a, W>
where
Error: From<W::Error>
{
type Ok = ();
type Error = Error;
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + serde_core::Serialize
{
SerializeSeq::serialize_element(&mut *self, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
SerializeSeq::end(self)
}
}
impl<'a, W: Write> serde_core::ser::SerializeTupleStruct for SeqSerializer<'a, W>
where
Error: From<W::Error>
{
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + serde_core::Serialize
{
SerializeSeq::serialize_element(&mut *self, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
SerializeSeq::end(self)
}
}
impl<'a, W: Write> serde_core::ser::SerializeTupleVariant for SeqSerializer<'a, W>
where
Error: From<W::Error>
{
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + serde_core::Serialize
{
SerializeSeq::serialize_element(&mut *self, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
self.ser.write_var_int(self.len as _)?;
self.ser.writer.take_from(self.subser.writer)?;
self.ser.writer.push(SerializationTag::EndDenseJSArray as _)?;
self.ser.writer.push(0)?; self.ser.write_var_int(self.len as _)?;
self.ser.writer.push(SerializationTag::EndJSObject as _)?;
self.ser.write_var_int(1)?;
Ok(())
}
}
pub(crate) struct MapSerializer<'a, W: Write>
where
Error: From<W::Error>
{
ser: &'a mut V8Serializer<W>,
entries: usize
}
impl<'a, W: Write> serde_core::ser::SerializeMap for MapSerializer<'a, W>
where
Error: From<W::Error>
{
type Ok = ();
type Error = Error;
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
where
T: ?Sized + serde_core::Serialize
{
key.serialize(&mut *self.ser)
}
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + serde_core::Serialize
{
let res = value.serialize(&mut *self.ser);
self.entries += 1;
res
}
fn end(self) -> Result<Self::Ok, Self::Error> {
self.ser.writer.push(SerializationTag::EndJSMap as _)?;
self.ser.write_var_int(self.entries as u32 * 2)?;
Ok(())
}
}
pub(crate) struct StructSerializer<'a, W: Write>
where
Error: From<W::Error>
{
ser: &'a mut V8Serializer<W>,
len: usize
}
impl<'a, W: Write> serde_core::ser::SerializeStruct for StructSerializer<'a, W>
where
Error: From<W::Error>
{
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + serde_core::Serialize
{
key.serialize(&mut *self.ser)?;
value.serialize(&mut *self.ser)?;
self.len += 1;
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
self.ser.writer.push(SerializationTag::EndJSObject as _)?;
self.ser.write_var_int(self.len as u32)?;
Ok(())
}
}
impl<'a, W: Write> serde_core::ser::SerializeStructVariant for StructSerializer<'a, W>
where
Error: From<W::Error>
{
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + serde_core::Serialize
{
SerializeStruct::serialize_field(self, key, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
self.ser.writer.push(SerializationTag::EndJSObject as _)?;
self.ser.write_var_int(self.len as u32)?;
self.ser.writer.push(SerializationTag::EndJSObject as _)?;
self.ser.write_var_int(1)?;
Ok(())
}
}
struct DateExtractor;
impl Serializer for DateExtractor {
type Ok = f64;
type Error = Error;
type SerializeMap = Impossible<Self::Ok, Self::Error>;
type SerializeSeq = Impossible<Self::Ok, Self::Error>;
type SerializeStruct = Impossible<Self::Ok, Self::Error>;
type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
type SerializeTuple = Impossible<Self::Ok, Self::Error>;
type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
Ok(v)
}
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_i128(self, _: i128) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
unreachable!()
}
fn serialize_newtype_struct<T>(self, _: &'static str, _: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize
{
unreachable!()
}
fn serialize_newtype_variant<T>(self, _: &'static str, _: u32, _: &'static str, _: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize
{
unreachable!()
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
unreachable!()
}
fn serialize_some<T>(self, _: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize
{
unreachable!()
}
fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeStruct, Self::Error> {
unreachable!()
}
fn serialize_struct_variant(self, _: &'static str, _: u32, _: &'static str, _: usize) -> Result<Self::SerializeStructVariant, Self::Error> {
unreachable!()
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
unreachable!()
}
fn serialize_tuple_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeTupleStruct, Self::Error> {
unreachable!()
}
fn serialize_tuple_variant(self, _: &'static str, _: u32, _: &'static str, _: usize) -> Result<Self::SerializeTupleVariant, Self::Error> {
unreachable!()
}
fn serialize_u128(self, _: u128) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
fn serialize_unit_variant(self, _: &'static str, _: u32, _: &'static str) -> Result<Self::Ok, Self::Error> {
unreachable!()
}
}
pub fn to_boxed_slice<T: ?Sized + Serialize>(value: &T, options: SerializeOptions) -> Result<Box<[u8]>, Error> {
let mut serializer = V8Serializer::new(SegmentedBuf::new(options.grow_strategy.clone()), options);
serializer.write_header()?;
value.serialize(&mut serializer)?;
Ok(serializer.writer.into_contiguous())
}
#[cfg(feature = "std")]
pub fn to_writer<T: ?Sized + Serialize>(value: &T, writer: impl io::Write, options: SerializeOptions) -> Result<(), Error> {
let mut serializer = V8Serializer::new(writer, options);
serializer.write_header()?;
value.serialize(&mut serializer)?;
Ok(())
}