Browse Source

Separate into files

feature/snapshot
Haled Odat 1 year ago
parent
commit
25356f6ccf
  1. 3
      boa_engine/src/context/mod.rs
  2. 25
      boa_engine/src/optimizer/mod.rs
  3. 113
      boa_engine/src/snapshot/deserializer.rs
  4. 25
      boa_engine/src/snapshot/error.rs
  5. 368
      boa_engine/src/snapshot/mod.rs
  6. 229
      boa_engine/src/snapshot/serializer.rs

3
boa_engine/src/context/mod.rs

@ -992,6 +992,7 @@ impl crate::snapshot::Serialize for Context<'_> {
s: &mut crate::snapshot::SnapshotSerializer, s: &mut crate::snapshot::SnapshotSerializer,
) -> Result<(), crate::snapshot::SnapshotError> { ) -> Result<(), crate::snapshot::SnapshotError> {
s.write_bool(self.strict)?; s.write_bool(self.strict)?;
self.optimizer_options.serialize(s)?;
self.realm.serialize(s)?; self.realm.serialize(s)?;
Ok(()) Ok(())
} }
@ -1002,9 +1003,11 @@ impl crate::snapshot::Deserialize for Context<'_> {
d: &mut crate::snapshot::SnapshotDeserializer<'_>, d: &mut crate::snapshot::SnapshotDeserializer<'_>,
) -> Result<Self, crate::snapshot::SnapshotError> { ) -> Result<Self, crate::snapshot::SnapshotError> {
let strict = d.read_bool()?; let strict = d.read_bool()?;
let optimizer_options = OptimizerOptions::deserialize(d)?;
let mut context = Context::default(); let mut context = Context::default();
context.strict(strict); context.strict(strict);
context.set_optimizer_options(optimizer_options);
Ok(context) Ok(context)
} }

25
boa_engine/src/optimizer/mod.rs

@ -4,7 +4,10 @@ pub(crate) mod pass;
pub(crate) mod walker; pub(crate) mod walker;
use self::{pass::ConstantFolding, walker::Walker}; use self::{pass::ConstantFolding, walker::Walker};
use crate::Context; use crate::{
snapshot::{Deserialize, Serialize},
Context,
};
use bitflags::bitflags; use bitflags::bitflags;
use boa_ast::{visitor::VisitorMut, Expression, StatementList}; use boa_ast::{visitor::VisitorMut, Expression, StatementList};
use std::{fmt, ops::ControlFlow}; use std::{fmt, ops::ControlFlow};
@ -24,6 +27,26 @@ bitflags! {
} }
} }
impl Serialize for OptimizerOptions {
fn serialize(
&self,
s: &mut crate::snapshot::SnapshotSerializer,
) -> Result<(), crate::snapshot::SnapshotError> {
s.write_u8(self.bits())?;
Ok(())
}
}
impl Deserialize for OptimizerOptions {
fn deserialize(
d: &mut crate::snapshot::SnapshotDeserializer<'_>,
) -> Result<Self, crate::snapshot::SnapshotError> {
let bits = d.read_u8()?;
// TODO: handle error.
Ok(OptimizerOptions::from_bits(bits).unwrap())
}
}
/// The action to be performed after an optimization step. /// The action to be performed after an optimization step.
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum PassAction<T> { pub(crate) enum PassAction<T> {

113
boa_engine/src/snapshot/deserializer.rs

@ -0,0 +1,113 @@
use indexmap::IndexSet;
use super::SnapshotError;
/// TODO: doc
pub trait Deserialize: Sized {
/// TODO: doc
fn deserialize(d: &mut SnapshotDeserializer<'_>) -> Result<Self, SnapshotError>;
}
/// TODO: doc
pub struct SnapshotDeserializer<'snapshot> {
pub(super) bytes: &'snapshot [u8],
pub(super) index: usize,
pub(super) external_references: &'snapshot IndexSet<usize>,
}
impl SnapshotDeserializer<'_> {
/// TODO: doc
pub fn read_bool(&mut self) -> Result<bool, SnapshotError> {
let byte = self.read_u8()?;
assert!(byte == 0 || byte == 1);
Ok(byte == 1)
}
/// TODO: doc
pub fn read_u8(&mut self) -> Result<u8, SnapshotError> {
let byte = self.bytes[self.index];
self.index += 1;
Ok(byte)
}
/// TODO: doc
pub fn read_i8(&mut self) -> Result<i8, SnapshotError> {
let byte = self.bytes[self.index];
self.index += 1;
Ok(byte as i8)
}
/// TODO: doc
pub fn read_u16(&mut self) -> Result<u16, SnapshotError> {
let bytes = self.read_bytes(std::mem::size_of::<u16>())?;
let value = u16::from_le_bytes([bytes[0], bytes[1]]);
Ok(value)
}
/// TODO: doc
pub fn read_i16(&mut self) -> Result<i16, SnapshotError> {
let value = self.read_u16()?;
Ok(value as i16)
}
/// TODO: doc
pub fn read_u32(&mut self) -> Result<u32, SnapshotError> {
let bytes = self.read_bytes(4)?;
let value = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
Ok(value)
}
/// TODO: doc
pub fn read_i32(&mut self) -> Result<i32, SnapshotError> {
let value = self.read_u32()?;
Ok(value as i32)
}
/// TODO: doc
pub fn read_f32(&mut self) -> Result<f32, SnapshotError> {
let value = self.read_u32()?;
Ok(f32::from_bits(value))
}
/// TODO: doc
pub fn read_f64(&mut self) -> Result<f64, SnapshotError> {
let value = self.read_u64()?;
Ok(f64::from_bits(value))
}
/// TODO: doc
pub fn read_u64(&mut self) -> Result<u64, SnapshotError> {
let bytes = self.read_bytes(std::mem::size_of::<u64>())?;
let value = u64::from_le_bytes([
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
]);
Ok(value)
}
/// TODO: doc
pub fn read_i64(&mut self) -> Result<i64, SnapshotError> {
let value = self.read_u64()?;
Ok(value as i64)
}
/// TODO: doc
pub fn read_usize(&mut self) -> Result<usize, SnapshotError> {
let value = self.read_u64()?;
// TODO: handle error.
Ok(usize::try_from(value).unwrap())
}
/// TODO: doc
pub fn read_isize(&mut self) -> Result<isize, SnapshotError> {
let value = self.read_usize()?;
Ok(value as isize)
}
/// TODO: doc
pub fn read_string(&mut self) -> Result<&str, SnapshotError> {
let len = self.read_usize()?;
let bytes = self.read_bytes(len)?;
// TODO: handle error
Ok(std::str::from_utf8(bytes).unwrap())
}
/// TODO: doc
pub fn read_bytes(&mut self, count: usize) -> Result<&[u8], SnapshotError> {
let index = self.index;
self.index += count;
// TODO: use .get() so we can handle the error.
let bytes = &self.bytes[index..(index + count)];
Ok(bytes)
}
}

25
boa_engine/src/snapshot/error.rs

@ -0,0 +1,25 @@
use std::fmt::{Debug, Display};
/// TODO: doc
#[derive(Debug)]
pub enum SnapshotError {
/// Input/output error.
///
/// See: [`std::io::Error`].
Io(std::io::Error),
}
impl Display for SnapshotError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// FIXME: implement better formatting
<Self as Debug>::fmt(self, f)
}
}
impl std::error::Error for SnapshotError {}
impl From<std::io::Error> for SnapshotError {
fn from(value: std::io::Error) -> Self {
Self::Io(value)
}
}

368
boa_engine/src/snapshot/mod.rs

@ -3,21 +3,17 @@
#![allow(missing_debug_implementations)] #![allow(missing_debug_implementations)]
#![allow(dead_code)] #![allow(dead_code)]
use crate::{Context, JsBigInt, JsObject, JsString, JsSymbol}; mod deserializer;
use indexmap::{IndexMap, IndexSet}; mod error;
use std::fmt::{Debug, Display}; mod serializer;
/// TODO: doc pub use deserializer::*;
pub trait Serialize { pub use error::*;
/// Serialize type pub use serializer::*;
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError>;
}
/// TODO: doc use crate::Context;
pub trait Deserialize: Sized { use indexmap::IndexSet;
/// TODO: doc use std::fmt::Debug;
fn deserialize(d: &mut SnapshotDeserializer<'_>) -> Result<Self, SnapshotError>;
}
/// TODO: doc /// TODO: doc
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -27,14 +23,6 @@ pub struct Header {
// checksum: u64, // checksum: u64,
} }
impl Serialize for Header {
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError> {
s.write_bytes(&self.signature)?;
s.write_u32(self.version)?;
Ok(())
}
}
impl Deserialize for Header { impl Deserialize for Header {
fn deserialize(d: &mut SnapshotDeserializer<'_>) -> Result<Self, SnapshotError> { fn deserialize(d: &mut SnapshotDeserializer<'_>) -> Result<Self, SnapshotError> {
let signature = d.read_bytes(4)?; let signature = d.read_bytes(4)?;
@ -46,15 +34,6 @@ impl Deserialize for Header {
} }
} }
impl Serialize for JsObject {
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError> {
let value = s.objects.insert_full(self.clone()).0;
s.write_u32(value as u32)?;
Ok(())
}
}
/// TODO: doc /// TODO: doc
pub struct Snapshot { pub struct Snapshot {
bytes: Vec<u8>, bytes: Vec<u8>,
@ -97,332 +76,3 @@ impl Snapshot {
Ok(context) Ok(context)
} }
} }
/// TODO: doc
pub struct SnapshotDeserializer<'snapshot> {
bytes: &'snapshot [u8],
index: usize,
external_references: &'snapshot IndexSet<usize>,
}
impl SnapshotDeserializer<'_> {
/// TODO: doc
pub fn read_bool(&mut self) -> Result<bool, SnapshotError> {
let byte = self.read_u8()?;
assert!(byte == 0 || byte == 1);
Ok(byte == 1)
}
/// TODO: doc
pub fn read_u8(&mut self) -> Result<u8, SnapshotError> {
let byte = self.bytes[self.index];
self.index += 1;
Ok(byte)
}
/// TODO: doc
pub fn read_i8(&mut self) -> Result<i8, SnapshotError> {
let byte = self.bytes[self.index];
self.index += 1;
Ok(byte as i8)
}
/// TODO: doc
pub fn read_u16(&mut self) -> Result<u16, SnapshotError> {
let bytes = self.read_bytes(std::mem::size_of::<u16>())?;
let value = u16::from_le_bytes([bytes[0], bytes[1]]);
Ok(value)
}
/// TODO: doc
pub fn read_i16(&mut self) -> Result<i16, SnapshotError> {
let value = self.read_u16()?;
Ok(value as i16)
}
/// TODO: doc
pub fn read_u32(&mut self) -> Result<u32, SnapshotError> {
let bytes = self.read_bytes(4)?;
let value = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
Ok(value)
}
/// TODO: doc
pub fn read_i32(&mut self) -> Result<i32, SnapshotError> {
let value = self.read_u32()?;
Ok(value as i32)
}
/// TODO: doc
pub fn read_f32(&mut self) -> Result<f32, SnapshotError> {
let value = self.read_u32()?;
Ok(f32::from_bits(value))
}
/// TODO: doc
pub fn read_f64(&mut self) -> Result<f64, SnapshotError> {
let value = self.read_u64()?;
Ok(f64::from_bits(value))
}
/// TODO: doc
pub fn read_u64(&mut self) -> Result<u64, SnapshotError> {
let bytes = self.read_bytes(std::mem::size_of::<u64>())?;
let value = u64::from_le_bytes([
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
]);
Ok(value)
}
/// TODO: doc
pub fn read_i64(&mut self) -> Result<i64, SnapshotError> {
let value = self.read_u64()?;
Ok(value as i64)
}
/// TODO: doc
pub fn read_usize(&mut self) -> Result<usize, SnapshotError> {
let value = self.read_u64()?;
// TODO: handle error.
Ok(usize::try_from(value).unwrap())
}
/// TODO: doc
pub fn read_isize(&mut self) -> Result<isize, SnapshotError> {
let value = self.read_usize()?;
Ok(value as isize)
}
/// TODO: doc
pub fn read_string(&mut self) -> Result<&str, SnapshotError> {
let len = self.read_usize()?;
let bytes = self.read_bytes(len)?;
// TODO: handle error
Ok(std::str::from_utf8(bytes).unwrap())
}
/// TODO: doc
pub fn read_bytes(&mut self, count: usize) -> Result<&[u8], SnapshotError> {
let index = self.index;
self.index += count;
// TODO: use .get() so we can handle the error.
let bytes = &self.bytes[index..(index + count)];
Ok(bytes)
}
}
/// TODO: doc
pub struct SnapshotSerializer {
bytes: Vec<u8>,
objects: IndexSet<JsObject>,
strings: IndexMap<usize, JsString>,
symbols: IndexMap<u64, JsSymbol>,
bigints: IndexSet<JsBigInt>,
external_references: IndexSet<usize>,
}
/// TODO: doc
#[derive(Debug)]
pub enum SnapshotError {
/// Input/output error.
///
/// See: [`std::io::Error`].
Io(std::io::Error),
}
impl Display for SnapshotError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// FIXME: implement better formatting
<Self as Debug>::fmt(self, f)
}
}
impl std::error::Error for SnapshotError {}
impl From<std::io::Error> for SnapshotError {
fn from(value: std::io::Error) -> Self {
Self::Io(value)
}
}
impl SnapshotSerializer {
/// TODO: doc
pub fn new() -> Self {
Self {
bytes: Vec::new(),
objects: IndexSet::default(),
strings: IndexMap::default(),
symbols: IndexMap::default(),
bigints: IndexSet::default(),
external_references: IndexSet::default(),
}
}
/// Serialize the given [`Context`].
pub fn serialize(mut self, context: &mut Context<'_>) -> Result<Snapshot, SnapshotError> {
// Remove any garbage objects before serialization.
boa_gc::force_collect();
// boa_gc::walk_gc_alloc_pointers(|address| {
// });
let header = Header {
signature: *b".boa",
version: 42,
};
header.serialize(&mut self)?;
context.serialize(&mut self)?;
for i in 0..self.objects.len() {
let object = self
.objects
.get_index(i)
.expect("There should be an object")
.clone();
object.inner().serialize(&mut self)?;
}
for i in 0..self.symbols.len() {
let (hash, symbol) = self
.symbols
.get_index(i)
.map(|(hash, symbol)| (*hash, symbol.clone()))
.expect("There should be an object");
self.write_u64(hash)?;
if let Some(desc) = symbol.description() {
self.write_bool(true)?;
desc.serialize(&mut self)?;
} else {
self.write_bool(false)?;
}
}
for i in 0..self.strings.len() {
let string = self
.strings
.get_index(i)
.expect("There should be an string")
.1
.clone();
// string.
string.serialize(&mut self)?;
self.write_bool(string.is_static())?;
self.write_usize(string.len())?;
for elem in string.as_slice() {
self.write_u16(*elem)?;
}
}
Ok(Snapshot {
bytes: self.bytes,
external_references: self.external_references,
})
}
/// TODO: doc
pub fn write_bool(&mut self, v: bool) -> Result<(), SnapshotError> {
Ok(self.write_u8(if v { 1 } else { 0 })?)
}
/// TODO: doc
pub fn write_u8(&mut self, v: u8) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&[v])?)
}
/// TODO: doc
pub fn write_i8(&mut self, v: i8) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_u16(&mut self, v: u16) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_i16(&mut self, v: i16) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_u32(&mut self, v: u32) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_i32(&mut self, v: i32) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_f32(&mut self, v: f32) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_f64(&mut self, v: f64) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_u64(&mut self, v: u64) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_i64(&mut self, v: i64) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_u128(&mut self, v: u128) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_i128(&mut self, v: i128) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_usize(&mut self, v: usize) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&(v as u64).to_le_bytes())?)
}
/// TODO: doc
pub fn write_isize(&mut self, v: isize) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&(v as i64).to_le_bytes())?)
}
/// TODO: doc
pub fn write_string(&mut self, v: &str) -> Result<(), SnapshotError> {
let asb = v.as_bytes();
self.write_usize(asb.len())?;
self.bytes.extend_from_slice(asb);
Ok(())
}
/// TODO: doc
pub fn write_bytes(&mut self, v: &[u8]) -> Result<(), SnapshotError> {
self.bytes.extend_from_slice(v);
Ok(())
}
}
impl<T: Serialize> Serialize for Vec<T> {
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError> {
s.write_usize(self.len())?;
for element in self {
element.serialize(s)?;
}
Ok(())
}
}
impl Serialize for JsString {
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError> {
let index = s.strings.insert_full(self.ptr.addr(), self.clone()).0;
s.write_u32(index as u32)?;
Ok(())
}
}
impl Serialize for JsSymbol {
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError> {
let index = s.symbols.insert_full(self.hash(), self.clone()).0;
s.write_u32(index as u32)?;
Ok(())
}
}
impl Serialize for JsBigInt {
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError> {
let index = s.bigints.insert_full(self.clone()).0;
s.write_u32(index as u32)?;
Ok(())
}
}

229
boa_engine/src/snapshot/serializer.rs

@ -0,0 +1,229 @@
use indexmap::{IndexMap, IndexSet};
use crate::{Context, JsBigInt, JsObject, JsString, JsSymbol};
use super::{Header, Snapshot, SnapshotError};
/// TODO: doc
pub trait Serialize {
/// Serialize type
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError>;
}
impl Serialize for Header {
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError> {
s.write_bytes(&self.signature)?;
s.write_u32(self.version)?;
Ok(())
}
}
/// TODO: doc
pub struct SnapshotSerializer {
bytes: Vec<u8>,
objects: IndexSet<JsObject>,
strings: IndexMap<usize, JsString>,
symbols: IndexMap<u64, JsSymbol>,
bigints: IndexSet<JsBigInt>,
external_references: IndexSet<usize>,
}
impl SnapshotSerializer {
/// TODO: doc
pub fn new() -> Self {
Self {
bytes: Vec::new(),
objects: IndexSet::default(),
strings: IndexMap::default(),
symbols: IndexMap::default(),
bigints: IndexSet::default(),
external_references: IndexSet::default(),
}
}
/// Serialize the given [`Context`].
pub fn serialize(mut self, context: &mut Context<'_>) -> Result<Snapshot, SnapshotError> {
// Remove any garbage objects before serialization.
boa_gc::force_collect();
// boa_gc::walk_gc_alloc_pointers(|address| {
// });
let header = Header {
signature: *b".boa",
version: 42,
};
header.serialize(&mut self)?;
context.serialize(&mut self)?;
for i in 0..self.objects.len() {
let object = self
.objects
.get_index(i)
.expect("There should be an object")
.clone();
object.inner().serialize(&mut self)?;
}
for i in 0..self.symbols.len() {
let (hash, symbol) = self
.symbols
.get_index(i)
.map(|(hash, symbol)| (*hash, symbol.clone()))
.expect("There should be an object");
self.write_u64(hash)?;
if let Some(desc) = symbol.description() {
self.write_bool(true)?;
desc.serialize(&mut self)?;
} else {
self.write_bool(false)?;
}
}
for i in 0..self.strings.len() {
let string = self
.strings
.get_index(i)
.expect("There should be an string")
.1
.clone();
// string.
string.serialize(&mut self)?;
self.write_bool(string.is_static())?;
self.write_usize(string.len())?;
for elem in string.as_slice() {
self.write_u16(*elem)?;
}
}
Ok(Snapshot {
bytes: self.bytes,
external_references: self.external_references,
})
}
/// TODO: doc
pub fn write_bool(&mut self, v: bool) -> Result<(), SnapshotError> {
Ok(self.write_u8(if v { 1 } else { 0 })?)
}
/// TODO: doc
pub fn write_u8(&mut self, v: u8) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&[v])?)
}
/// TODO: doc
pub fn write_i8(&mut self, v: i8) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_u16(&mut self, v: u16) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_i16(&mut self, v: i16) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_u32(&mut self, v: u32) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_i32(&mut self, v: i32) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_f32(&mut self, v: f32) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_f64(&mut self, v: f64) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_u64(&mut self, v: u64) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_i64(&mut self, v: i64) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_u128(&mut self, v: u128) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_i128(&mut self, v: i128) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&v.to_le_bytes())?)
}
/// TODO: doc
pub fn write_usize(&mut self, v: usize) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&(v as u64).to_le_bytes())?)
}
/// TODO: doc
pub fn write_isize(&mut self, v: isize) -> Result<(), SnapshotError> {
Ok(self.write_bytes(&(v as i64).to_le_bytes())?)
}
/// TODO: doc
pub fn write_string(&mut self, v: &str) -> Result<(), SnapshotError> {
let asb = v.as_bytes();
self.write_usize(asb.len())?;
self.bytes.extend_from_slice(asb);
Ok(())
}
/// TODO: doc
pub fn write_bytes(&mut self, v: &[u8]) -> Result<(), SnapshotError> {
self.bytes.extend_from_slice(v);
Ok(())
}
}
impl<T: Serialize> Serialize for Vec<T> {
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError> {
s.write_usize(self.len())?;
for element in self {
element.serialize(s)?;
}
Ok(())
}
}
impl Serialize for JsString {
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError> {
let index = s.strings.insert_full(self.ptr.addr(), self.clone()).0;
s.write_u32(index as u32)?;
Ok(())
}
}
impl Serialize for JsSymbol {
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError> {
let index = s.symbols.insert_full(self.hash(), self.clone()).0;
s.write_u32(index as u32)?;
Ok(())
}
}
impl Serialize for JsBigInt {
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError> {
let index = s.bigints.insert_full(self.clone()).0;
s.write_u32(index as u32)?;
Ok(())
}
}
impl Serialize for JsObject {
fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError> {
let value = s.objects.insert_full(self.clone()).0;
s.write_u32(value as u32)?;
Ok(())
}
}
Loading…
Cancel
Save