From 25356f6ccfc9dfe74b8825d047cfbec7d6c60710 Mon Sep 17 00:00:00 2001 From: Haled Odat <8566042+HalidOdat@users.noreply.github.com> Date: Wed, 21 Jun 2023 18:10:07 +0200 Subject: [PATCH] Separate into files --- boa_engine/src/context/mod.rs | 3 + boa_engine/src/optimizer/mod.rs | 25 +- boa_engine/src/snapshot/deserializer.rs | 113 ++++++++ boa_engine/src/snapshot/error.rs | 25 ++ boa_engine/src/snapshot/mod.rs | 368 +----------------------- boa_engine/src/snapshot/serializer.rs | 229 +++++++++++++++ 6 files changed, 403 insertions(+), 360 deletions(-) create mode 100644 boa_engine/src/snapshot/deserializer.rs create mode 100644 boa_engine/src/snapshot/error.rs create mode 100644 boa_engine/src/snapshot/serializer.rs diff --git a/boa_engine/src/context/mod.rs b/boa_engine/src/context/mod.rs index 96e950d2ea..2766b91e0a 100644 --- a/boa_engine/src/context/mod.rs +++ b/boa_engine/src/context/mod.rs @@ -992,6 +992,7 @@ impl crate::snapshot::Serialize for Context<'_> { s: &mut crate::snapshot::SnapshotSerializer, ) -> Result<(), crate::snapshot::SnapshotError> { s.write_bool(self.strict)?; + self.optimizer_options.serialize(s)?; self.realm.serialize(s)?; Ok(()) } @@ -1002,9 +1003,11 @@ impl crate::snapshot::Deserialize for Context<'_> { d: &mut crate::snapshot::SnapshotDeserializer<'_>, ) -> Result { let strict = d.read_bool()?; + let optimizer_options = OptimizerOptions::deserialize(d)?; let mut context = Context::default(); context.strict(strict); + context.set_optimizer_options(optimizer_options); Ok(context) } diff --git a/boa_engine/src/optimizer/mod.rs b/boa_engine/src/optimizer/mod.rs index e675a72a71..ce33482289 100644 --- a/boa_engine/src/optimizer/mod.rs +++ b/boa_engine/src/optimizer/mod.rs @@ -4,7 +4,10 @@ pub(crate) mod pass; pub(crate) mod walker; use self::{pass::ConstantFolding, walker::Walker}; -use crate::Context; +use crate::{ + snapshot::{Deserialize, Serialize}, + Context, +}; use bitflags::bitflags; use boa_ast::{visitor::VisitorMut, Expression, StatementList}; 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 { + let bits = d.read_u8()?; + + // TODO: handle error. + Ok(OptimizerOptions::from_bits(bits).unwrap()) + } +} + /// The action to be performed after an optimization step. #[derive(Debug)] pub(crate) enum PassAction { diff --git a/boa_engine/src/snapshot/deserializer.rs b/boa_engine/src/snapshot/deserializer.rs new file mode 100644 index 0000000000..cdf324c151 --- /dev/null +++ b/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; +} + +/// TODO: doc +pub struct SnapshotDeserializer<'snapshot> { + pub(super) bytes: &'snapshot [u8], + pub(super) index: usize, + pub(super) external_references: &'snapshot IndexSet, +} + +impl SnapshotDeserializer<'_> { + /// TODO: doc + pub fn read_bool(&mut self) -> Result { + let byte = self.read_u8()?; + assert!(byte == 0 || byte == 1); + Ok(byte == 1) + } + /// TODO: doc + pub fn read_u8(&mut self) -> Result { + let byte = self.bytes[self.index]; + self.index += 1; + Ok(byte) + } + /// TODO: doc + pub fn read_i8(&mut self) -> Result { + let byte = self.bytes[self.index]; + self.index += 1; + Ok(byte as i8) + } + + /// TODO: doc + pub fn read_u16(&mut self) -> Result { + let bytes = self.read_bytes(std::mem::size_of::())?; + let value = u16::from_le_bytes([bytes[0], bytes[1]]); + Ok(value) + } + /// TODO: doc + pub fn read_i16(&mut self) -> Result { + let value = self.read_u16()?; + Ok(value as i16) + } + + /// TODO: doc + pub fn read_u32(&mut self) -> Result { + 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 { + let value = self.read_u32()?; + Ok(value as i32) + } + + /// TODO: doc + pub fn read_f32(&mut self) -> Result { + let value = self.read_u32()?; + Ok(f32::from_bits(value)) + } + /// TODO: doc + pub fn read_f64(&mut self) -> Result { + let value = self.read_u64()?; + Ok(f64::from_bits(value)) + } + + /// TODO: doc + pub fn read_u64(&mut self) -> Result { + let bytes = self.read_bytes(std::mem::size_of::())?; + 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 { + let value = self.read_u64()?; + Ok(value as i64) + } + + /// TODO: doc + pub fn read_usize(&mut self) -> Result { + let value = self.read_u64()?; + // TODO: handle error. + Ok(usize::try_from(value).unwrap()) + } + /// TODO: doc + pub fn read_isize(&mut self) -> Result { + 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) + } +} diff --git a/boa_engine/src/snapshot/error.rs b/boa_engine/src/snapshot/error.rs new file mode 100644 index 0000000000..3abb209d29 --- /dev/null +++ b/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 + ::fmt(self, f) + } +} + +impl std::error::Error for SnapshotError {} + +impl From for SnapshotError { + fn from(value: std::io::Error) -> Self { + Self::Io(value) + } +} diff --git a/boa_engine/src/snapshot/mod.rs b/boa_engine/src/snapshot/mod.rs index cbcbe4bf70..aa34de6548 100644 --- a/boa_engine/src/snapshot/mod.rs +++ b/boa_engine/src/snapshot/mod.rs @@ -3,21 +3,17 @@ #![allow(missing_debug_implementations)] #![allow(dead_code)] -use crate::{Context, JsBigInt, JsObject, JsString, JsSymbol}; -use indexmap::{IndexMap, IndexSet}; -use std::fmt::{Debug, Display}; +mod deserializer; +mod error; +mod serializer; -/// TODO: doc -pub trait Serialize { - /// Serialize type - fn serialize(&self, s: &mut SnapshotSerializer) -> Result<(), SnapshotError>; -} +pub use deserializer::*; +pub use error::*; +pub use serializer::*; -/// TODO: doc -pub trait Deserialize: Sized { - /// TODO: doc - fn deserialize(d: &mut SnapshotDeserializer<'_>) -> Result; -} +use crate::Context; +use indexmap::IndexSet; +use std::fmt::Debug; /// TODO: doc #[derive(Debug, Clone, Copy)] @@ -27,14 +23,6 @@ pub struct Header { // 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 { fn deserialize(d: &mut SnapshotDeserializer<'_>) -> Result { 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 pub struct Snapshot { bytes: Vec, @@ -97,332 +76,3 @@ impl Snapshot { Ok(context) } } - -/// TODO: doc -pub struct SnapshotDeserializer<'snapshot> { - bytes: &'snapshot [u8], - index: usize, - external_references: &'snapshot IndexSet, -} - -impl SnapshotDeserializer<'_> { - /// TODO: doc - pub fn read_bool(&mut self) -> Result { - let byte = self.read_u8()?; - assert!(byte == 0 || byte == 1); - Ok(byte == 1) - } - /// TODO: doc - pub fn read_u8(&mut self) -> Result { - let byte = self.bytes[self.index]; - self.index += 1; - Ok(byte) - } - /// TODO: doc - pub fn read_i8(&mut self) -> Result { - let byte = self.bytes[self.index]; - self.index += 1; - Ok(byte as i8) - } - - /// TODO: doc - pub fn read_u16(&mut self) -> Result { - let bytes = self.read_bytes(std::mem::size_of::())?; - let value = u16::from_le_bytes([bytes[0], bytes[1]]); - Ok(value) - } - /// TODO: doc - pub fn read_i16(&mut self) -> Result { - let value = self.read_u16()?; - Ok(value as i16) - } - - /// TODO: doc - pub fn read_u32(&mut self) -> Result { - 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 { - let value = self.read_u32()?; - Ok(value as i32) - } - - /// TODO: doc - pub fn read_f32(&mut self) -> Result { - let value = self.read_u32()?; - Ok(f32::from_bits(value)) - } - /// TODO: doc - pub fn read_f64(&mut self) -> Result { - let value = self.read_u64()?; - Ok(f64::from_bits(value)) - } - - /// TODO: doc - pub fn read_u64(&mut self) -> Result { - let bytes = self.read_bytes(std::mem::size_of::())?; - 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 { - let value = self.read_u64()?; - Ok(value as i64) - } - - /// TODO: doc - pub fn read_usize(&mut self) -> Result { - let value = self.read_u64()?; - // TODO: handle error. - Ok(usize::try_from(value).unwrap()) - } - /// TODO: doc - pub fn read_isize(&mut self) -> Result { - 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, - objects: IndexSet, - strings: IndexMap, - symbols: IndexMap, - bigints: IndexSet, - external_references: IndexSet, -} - -/// 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 - ::fmt(self, f) - } -} - -impl std::error::Error for SnapshotError {} - -impl From 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 { - // 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 Serialize for Vec { - 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(()) - } -} diff --git a/boa_engine/src/snapshot/serializer.rs b/boa_engine/src/snapshot/serializer.rs new file mode 100644 index 0000000000..2f3e99f8fc --- /dev/null +++ b/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, + objects: IndexSet, + strings: IndexMap, + symbols: IndexMap, + bigints: IndexSet, + external_references: IndexSet, +} + +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 { + // 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 Serialize for Vec { + 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(()) + } +}