rspack_cacheable/
serialize.rs

1use std::any::Any;
2
3use rkyv::{
4  Serialize,
5  api::{high::HighSerializer, serialize_using},
6  rancor::{BoxedError, Source, Trace},
7  ser::{
8    Serializer as RkyvSerializer,
9    allocator::{Arena, ArenaHandle},
10    sharing::Share,
11  },
12  util::AlignedVec,
13};
14
15use crate::context::ContextGuard;
16
17#[derive(Debug)]
18pub enum SerializeError {
19  BoxedError(BoxedError),
20  MessageError(&'static str),
21  NoContext,
22  UnsupportedField,
23}
24
25impl std::fmt::Display for SerializeError {
26  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27    match self {
28      Self::BoxedError(error) => error.fmt(f),
29      Self::MessageError(msg) => {
30        write!(f, "{msg}")
31      }
32      Self::NoContext => {
33        write!(f, "no context")
34      }
35      Self::UnsupportedField => {
36        write!(f, "unsupported field")
37      }
38    }
39  }
40}
41
42impl std::error::Error for SerializeError {
43  fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
44    match self {
45      Self::BoxedError(error) => error.source(),
46      _ => None,
47    }
48  }
49}
50
51impl Trace for SerializeError {
52  fn trace<R>(self, trace: R) -> Self
53  where
54    R: std::fmt::Debug + std::fmt::Display + Send + Sync + 'static,
55  {
56    Self::BoxedError(BoxedError::trace(BoxedError::new(self), trace))
57  }
58}
59
60impl Source for SerializeError {
61  fn new<T: std::error::Error + Send + Sync + 'static>(source: T) -> Self {
62    Self::BoxedError(BoxedError::new(source))
63  }
64}
65
66pub type Serializer<'a> = HighSerializer<AlignedVec, ArenaHandle<'a>, SerializeError>;
67
68/// Transform struct to bytes
69///
70/// This function implementation refers to rkyv::to_bytes and
71/// add custom error and context support
72pub fn to_bytes<T, C: Any>(value: &T, ctx: &C) -> Result<Vec<u8>, SerializeError>
73where
74  T: for<'a> Serialize<Serializer<'a>>,
75{
76  let guard = ContextGuard::new(ctx);
77  let mut arena = Arena::new();
78  let mut serializer = RkyvSerializer::new(AlignedVec::new(), arena.acquire(), Share::new());
79  guard.add_to_sharing(&mut serializer)?;
80
81  serialize_using(value, &mut serializer)?;
82  Ok(serializer.into_writer().into_vec())
83}