1use std::collections::HashMap;
2
3use num_bigint::BigInt;
4use thiserror::Error;
5
6use crate::tags::ArrayBufferViewTag;
7use crate::tags::ErrorTag;
8use crate::tags::SerializationTag;
9use crate::value::ArrayBuffer;
10use crate::value::ArrayBufferView;
11use crate::value::ArrayBufferViewKind;
12use crate::value::Date;
13use crate::value::DenseArray;
14use crate::value::Error;
15use crate::value::ErrorName;
16use crate::value::Map;
17use crate::value::Object;
18use crate::value::PropertyKey;
19use crate::value::RegExp;
20use crate::value::Set;
21use crate::value::SparseArray;
22use crate::Heap;
23use crate::HeapReference;
24use crate::HeapValue;
25use crate::StringValue;
26use crate::Value;
27
28#[derive(Debug, Error)]
29pub enum SerializationError {
30  #[error("recursion depth limit exceeded")]
31  RecursionDepthLimitExceeded,
32  #[error("a dangling heap reference was encountered")]
33  DanglingHeapReference,
34  #[error("a string was too long to serialize")]
35  StringTooLong,
36  #[error("a BigInt was too large to serialize")]
37  BigIntTooLarge,
38  #[error("an object has too many properties to serialize")]
39  TooManyObjectProperties,
40  #[error("an array has too many elements to serialize")]
41  ArrayTooLong,
42  #[error("a map has too many entries to serialize")]
43  MapTooLarge,
44  #[error("a set has too many entries to serialize")]
45  SetTooLarge,
46}
47
48#[derive(Default)]
49pub struct ValueSerializer {
50  data: Vec<u8>,
51  id_map: HashMap<HeapReference, u32>,
52  recursion_depth: usize,
53}
54
55const RECURSION_DEPTH_LIMIT: usize = 256;
56const WIRE_FORMAT_VERSION: u32 = 15;
57
58impl ValueSerializer {
59  pub fn finish(
60    mut self,
61    heap: &Heap,
62    value: &Value,
63  ) -> Result<Vec<u8>, SerializationError> {
64    self.write_header();
65    self.write_value(heap, value)?;
66    Ok(self.data)
67  }
68
69  fn write_header(&mut self) {
70    self.write_tag(SerializationTag::Version);
71    self.write_varint(WIRE_FORMAT_VERSION);
72  }
73
74  fn write_value(
75    &mut self,
76    heap: &Heap,
77    value: &Value,
78  ) -> Result<(), SerializationError> {
79    match value {
80      Value::Undefined => self.write_tag(SerializationTag::Undefined),
81      Value::Null => self.write_tag(SerializationTag::Null),
82      Value::Bool(true) => self.write_tag(SerializationTag::True),
83      Value::Bool(false) => self.write_tag(SerializationTag::False),
84      Value::I32(smi) => self.write_smi(*smi),
85      Value::U32(int) => self.write_u32(int),
86      Value::Double(double) => self.write_number(*double),
87      Value::BigInt(bigint) => self.write_bigint(bigint)?,
88      Value::String(str) => self.write_string(str)?,
89      Value::HeapReference(reference) => {
90        self.recursion_depth += 1;
91        self.write_heap_reference(heap, *reference)?;
92        self.recursion_depth -= 1;
93      }
94    };
95    Ok(())
96  }
97
98  fn write_tag(&mut self, tag: SerializationTag) {
99    self.data.push(tag as u8)
100  }
101
102  fn write_varint(&mut self, value: u32) {
103    let mut value = value;
108    while value >= 0x80 {
109      self.data.push(((value & 0x7f) | 0x80) as u8);
110      value >>= 7;
111    }
112    self.data.push(value as u8);
113  }
114
115  fn write_varint_u8(&mut self, value: u8) {
116    self.write_varint(value as u32);
117  }
118
119  fn write_zigzag(&mut self, value: i32) {
120    self.write_varint(
124      ((value << 1) ^ (value >> (i32::BITS as usize - 1))) as u32,
125    );
126  }
127
128  fn write_double(&mut self, value: f64) {
129    self.data.extend_from_slice(&value.to_le_bytes());
130  }
131
132  fn write_smi(&mut self, val: i32) {
133    self.write_tag(SerializationTag::Int32);
134    self.write_zigzag(val);
135  }
136
137  fn write_u32(&mut self, int: &u32) {
138    self.write_tag(SerializationTag::Uint32);
139    self.write_varint(*int);
140  }
141
142  fn write_number(&mut self, val: f64) {
143    self.write_tag(SerializationTag::Double);
144    self.write_double(val);
145  }
146
147  fn write_bigint(&mut self, val: &BigInt) -> Result<(), SerializationError> {
148    self.write_tag(SerializationTag::BigInt);
149    self.write_bigint_contents(val)?;
150    Ok(())
151  }
152
153  fn write_bigint_contents(
154    &mut self,
155    val: &BigInt,
156  ) -> Result<(), SerializationError> {
157    let (sign, bytes) = val.to_bytes_le();
158    let mut bitfield = 0u32;
159    if sign == num_bigint::Sign::Minus {
160      bitfield |= 1;
161    }
162    let length: u32 = bytes
163      .len()
164      .try_into()
165      .map_err(|_| SerializationError::BigIntTooLarge)?;
166    if length > 0x7fff_ffff {
167      return Err(SerializationError::BigIntTooLarge);
168    }
169    bitfield |= length << 1;
170    self.write_varint(bitfield);
171    self.data.extend_from_slice(&bytes);
172    Ok(())
173  }
174
175  fn write_string(
176    &mut self,
177    str: &StringValue,
178  ) -> Result<(), SerializationError> {
179    match str {
180      StringValue::Wtf8(wtf8) => {
181        self.write_tag(SerializationTag::Utf8String);
182        let bytes = wtf8.as_bytes();
183        let length: u32 = bytes
184          .len()
185          .try_into()
186          .map_err(|_| SerializationError::StringTooLong)?;
187        self.write_varint(length);
188        self.data.extend_from_slice(bytes);
189      }
190      StringValue::OneByte(str) => {
191        self.write_tag(SerializationTag::OneByteString);
192        let bytes = str.as_bytes();
193        let length: u32 = str
194          .as_bytes()
195          .len()
196          .try_into()
197          .map_err(|_| SerializationError::StringTooLong)?;
198        self.write_varint(length);
199        self.data.extend_from_slice(bytes);
200      }
201      StringValue::TwoByte(str) => {
202        let bytes = str.as_u8_bytes();
203        let length: u32 = bytes
204          .len()
205          .try_into()
206          .map_err(|_| SerializationError::StringTooLong)?;
207        if (self.data.len() + 1 + bytes_needed_for_varint(length)) & 0x1 == 1 {
208          self.write_tag(SerializationTag::Padding);
209        }
210        self.write_tag(SerializationTag::TwoByteString);
211        self.write_varint(length);
212        self.data.extend_from_slice(bytes);
213      }
214    }
215    Ok(())
216  }
217
218  fn write_heap_reference(
219    &mut self,
220    heap: &Heap,
221    reference: HeapReference,
222  ) -> Result<(), SerializationError> {
223    let Some(value) = reference.try_open(heap) else {
224      return Err(SerializationError::DanglingHeapReference);
225    };
226    match value {
227      HeapValue::ArrayBufferView(abv)
228        if !self.id_map.contains_key(&reference) =>
229      {
230        self.recursion_depth += 1;
231        self.write_heap_reference(heap, abv.buffer)?;
232        self.recursion_depth -= 1;
233        self.write_heap_value_inner(heap, reference, value)
234      }
235      _ => self.write_heap_value_inner(heap, reference, value),
236    }
237  }
238
239  fn write_heap_value_inner(
240    &mut self,
241    heap: &Heap,
242    reference: HeapReference,
243    value: &HeapValue,
244  ) -> Result<(), SerializationError> {
245    let next_id: u32 = self.id_map.len() as u32;
246    match self.id_map.entry(reference) {
247      std::collections::hash_map::Entry::Occupied(entry) => {
248        let id = *entry.get();
249        self.write_tag(SerializationTag::ObjectReference);
250        self.write_varint(id);
251        return Ok(());
252      }
253      std::collections::hash_map::Entry::Vacant(entry) => {
254        entry.insert(next_id);
255      }
256    };
257
258    if self.recursion_depth > RECURSION_DEPTH_LIMIT {
259      return Err(SerializationError::RecursionDepthLimitExceeded);
260    }
261
262    match value {
263      HeapValue::BooleanObject(true) => {
264        self.write_tag(SerializationTag::TrueObject);
265      }
266      HeapValue::BooleanObject(false) => {
267        self.write_tag(SerializationTag::FalseObject);
268      }
269      HeapValue::NumberObject(double) => {
270        self.write_tag(SerializationTag::NumberObject);
271        self.write_double(*double);
272      }
273      HeapValue::BigIntObject(bigint) => {
274        self.write_tag(SerializationTag::BigIntObject);
275        self.write_bigint_contents(bigint)?;
276      }
277      HeapValue::StringObject(str) => {
278        self.write_tag(SerializationTag::StringObject);
279        self.write_string(str)?;
280      }
281      HeapValue::RegExp(regexp) => self.write_regexp(regexp)?,
282      HeapValue::Date(date) => {
283        self.write_date(date);
284      }
285      HeapValue::Object(obj) => self.write_object(heap, obj)?,
286      HeapValue::SparseArray(arr) => self.write_sparse_array(heap, arr)?,
287      HeapValue::DenseArray(arr) => self.write_dense_array(heap, arr)?,
288      HeapValue::Map(map) => self.write_map(heap, map)?,
289      HeapValue::Set(set) => self.write_set(heap, set)?,
290      HeapValue::ArrayBuffer(ab) => self.write_array_buffer(ab),
291      HeapValue::ArrayBufferView(abv) => self.write_array_buffer_view(abv),
292      HeapValue::Error(err) => self.write_error(heap, err)?,
293    };
294    Ok(())
295  }
296
297  fn write_regexp(
298    &mut self,
299    regexp: &RegExp,
300  ) -> Result<(), SerializationError> {
301    self.write_tag(SerializationTag::RegExp);
302    self.write_string(®exp.pattern)?;
303    self.write_varint(regexp.flags.bits());
304    Ok(())
305  }
306
307  fn write_date(&mut self, date: &Date) {
308    self.write_tag(SerializationTag::Date);
309    self.write_double(date.time_since_epoch);
310  }
311
312  fn write_object(
313    &mut self,
314    heap: &Heap,
315    obj: &Object,
316  ) -> Result<(), SerializationError> {
317    self.write_tag(SerializationTag::BeginJsObject);
318    self.write_object_properties(
319      heap,
320      &obj.properties,
321      SerializationTag::EndJsObject,
322    )?;
323    Ok(())
324  }
325
326  fn write_object_properties(
327    &mut self,
328    heap: &Heap,
329    properties: &[(PropertyKey, Value)],
330    end_tag: SerializationTag,
331  ) -> Result<(), SerializationError> {
332    let property_count: u32 = properties
333      .len()
334      .try_into()
335      .map_err(|_| SerializationError::TooManyObjectProperties)?;
336    for (key, value) in properties {
337      match key {
338        PropertyKey::I32(smi) => self.write_smi(*smi),
339        PropertyKey::U32(num) => self.write_u32(num),
340        PropertyKey::Double(double) => self.write_number(*double),
341        PropertyKey::String(str) => self.write_string(str)?,
342      }
343      self.write_value(heap, value)?;
344    }
345    self.write_tag(end_tag);
346    self.write_varint(property_count);
347    Ok(())
348  }
349
350  fn write_sparse_array(
351    &mut self,
352    heap: &Heap,
353    arr: &SparseArray,
354  ) -> Result<(), SerializationError> {
355    self.write_tag(SerializationTag::BeginSparseJsArray);
356    self.write_varint(arr.length);
357    self.write_object_properties(
358      heap,
359      &arr.properties,
360      SerializationTag::EndSparseJsArray,
361    )?;
362    self.write_varint(arr.length);
363    Ok(())
364  }
365
366  fn write_dense_array(
367    &mut self,
368    heap: &Heap,
369    arr: &DenseArray,
370  ) -> Result<(), SerializationError> {
371    self.write_tag(SerializationTag::BeginDenseJsArray);
372    let length: u32 = arr
373      .elements
374      .len()
375      .try_into()
376      .map_err(|_| SerializationError::ArrayTooLong)?;
377    self.write_varint(length);
378    for value in &arr.elements {
379      if let Some(value) = value {
380        self.write_value(heap, value)?;
381      } else {
382        self.write_tag(SerializationTag::TheHole);
383      }
384    }
385    self.write_object_properties(
386      heap,
387      &arr.properties,
388      SerializationTag::EndDenseJsArray,
389    )?;
390    self.write_varint(length);
391    Ok(())
392  }
393
394  fn write_map(
395    &mut self,
396    heap: &Heap,
397    map: &Map,
398  ) -> Result<(), SerializationError> {
399    let size: u32 = map
400      .entries
401      .len()
402      .try_into()
403      .map_err(|_| SerializationError::MapTooLarge)?;
404    let length = size.checked_mul(2).ok_or(SerializationError::MapTooLarge)?;
405    self.write_tag(SerializationTag::BeginJsMap);
406    for (key, value) in &map.entries {
407      self.write_value(heap, key)?;
408      self.write_value(heap, value)?;
409    }
410    self.write_tag(SerializationTag::EndJsMap);
411    self.write_varint(length);
412    Ok(())
413  }
414
415  fn write_set(
416    &mut self,
417    heap: &Heap,
418    set: &Set,
419  ) -> Result<(), SerializationError> {
420    let size: u32 = set
421      .values
422      .len()
423      .try_into()
424      .map_err(|_| SerializationError::SetTooLarge)?;
425    self.write_tag(SerializationTag::BeginJsSet);
426    for value in &set.values {
427      self.write_value(heap, value)?;
428    }
429    self.write_tag(SerializationTag::EndJsSet);
430    self.write_varint(size);
431    Ok(())
432  }
433
434  fn write_array_buffer(&mut self, ab: &ArrayBuffer) {
435    if let Some(max_byte_length) = ab.max_byte_length {
436      self.write_tag(SerializationTag::ResizableArrayBuffer);
437      self.write_varint(ab.byte_length());
438      self.write_varint(max_byte_length);
439    } else {
440      self.write_tag(SerializationTag::ArrayBuffer);
441      self.write_varint(ab.byte_length());
442    }
443    self.data.extend_from_slice(ab.as_u8_slice());
444  }
445
446  fn write_array_buffer_view(&mut self, abv: &ArrayBufferView) {
447    self.write_tag(SerializationTag::ArrayBufferView);
448    let tag = match abv.kind {
449      ArrayBufferViewKind::Int8Array => ArrayBufferViewTag::Int8Array,
450      ArrayBufferViewKind::Uint8Array => ArrayBufferViewTag::Uint8Array,
451      ArrayBufferViewKind::Uint8ClampedArray => {
452        ArrayBufferViewTag::Uint8ClampedArray
453      }
454      ArrayBufferViewKind::Int16Array => ArrayBufferViewTag::Int16Array,
455      ArrayBufferViewKind::Uint16Array => ArrayBufferViewTag::Uint16Array,
456      ArrayBufferViewKind::Int32Array => ArrayBufferViewTag::Int32Array,
457      ArrayBufferViewKind::Uint32Array => ArrayBufferViewTag::Uint32Array,
458      ArrayBufferViewKind::Float32Array => ArrayBufferViewTag::Float32Array,
459      ArrayBufferViewKind::Float64Array => ArrayBufferViewTag::Float64Array,
460      ArrayBufferViewKind::BigInt64Array => ArrayBufferViewTag::BigInt64Array,
461      ArrayBufferViewKind::BigUint64Array => ArrayBufferViewTag::BigUint64Array,
462      ArrayBufferViewKind::DataView => ArrayBufferViewTag::DataView,
463    };
464    self.write_varint_u8(tag as u8);
465    self.write_varint(abv.byte_offset);
466    self.write_varint(abv.length * abv.kind.byte_width());
467    let mut flags = 0u32;
468    if abv.is_length_tracking {
469      flags |= 0b1;
470    }
471    if abv.is_backed_by_rab {
472      flags |= 0b10;
473    }
474    self.write_varint(flags);
475  }
476
477  fn write_error(
478    &mut self,
479    heap: &Heap,
480    err: &Error,
481  ) -> Result<(), SerializationError> {
482    self.write_tag(SerializationTag::Error);
483    let name_tag = match err.name {
484      ErrorName::Error => None,
485      ErrorName::EvalError => Some(ErrorTag::EvalErrorPrototype),
486      ErrorName::RangeError => Some(ErrorTag::RangeErrorPrototype),
487      ErrorName::ReferenceError => Some(ErrorTag::ReferenceErrorPrototype),
488      ErrorName::SyntaxError => Some(ErrorTag::SyntaxErrorPrototype),
489      ErrorName::TypeError => Some(ErrorTag::TypeErrorPrototype),
490      ErrorName::UriError => Some(ErrorTag::UriErrorPrototype),
491    };
492    if let Some(tag) = name_tag {
493      self.write_varint(tag as u32);
494    }
495    if let Some(message) = &err.message {
496      self.write_varint(ErrorTag::Message as u32);
497      self.write_string(message)?;
498    }
499    if let Some(cause) = &err.cause {
500      self.write_varint(ErrorTag::Cause as u32);
501      self.write_value(heap, cause)?;
502    }
503    if let Some(stack) = &err.stack {
504      self.write_varint(ErrorTag::Stack as u32);
505      self.write_string(stack)?;
506    }
507
508    self.write_varint(ErrorTag::End as u32);
509
510    Ok(())
511  }
512}
513
514fn bytes_needed_for_varint(value: u32) -> usize {
515  let mut value = value;
516  let mut bytes = 1;
517  while value >= 0x80 {
518    bytes += 1;
519    value >>= 7;
520  }
521  bytes
522}