rspack_cacheable/with/
as_inner.rs

1use rkyv::{
2  munge::munge,
3  option::ArchivedOption,
4  rancor::Fallible,
5  traits::NoUndef,
6  with::{ArchiveWith, DeserializeWith, SerializeWith},
7  Place,
8};
9
10use crate::with::AsCacheable;
11
12pub struct AsInner<T = AsCacheable> {
13  _inner: T,
14}
15
16pub trait AsInnerConverter {
17  type Inner;
18  fn to_inner(&self) -> &Self::Inner;
19  fn from_inner(data: Self::Inner) -> Self;
20}
21
22impl<T, O, A> ArchiveWith<T> for AsInner<A>
23where
24  T: AsInnerConverter<Inner = O>,
25  A: ArchiveWith<O>,
26{
27  type Archived = A::Archived;
28  type Resolver = A::Resolver;
29
30  #[inline]
31  fn resolve_with(field: &T, resolver: Self::Resolver, out: Place<Self::Archived>) {
32    A::resolve_with(field.to_inner(), resolver, out)
33  }
34}
35
36impl<T, A, O, S> SerializeWith<T, S> for AsInner<A>
37where
38  T: AsInnerConverter<Inner = O>,
39  S: Fallible + ?Sized,
40  A: ArchiveWith<O> + SerializeWith<O, S>,
41{
42  fn serialize_with(field: &T, s: &mut S) -> Result<Self::Resolver, S::Error> {
43    A::serialize_with(field.to_inner(), s)
44  }
45}
46
47impl<T, A, O, D> DeserializeWith<A::Archived, T, D> for AsInner<A>
48where
49  T: AsInnerConverter<Inner = O>,
50  A: ArchiveWith<O> + DeserializeWith<A::Archived, O, D>,
51  D: Fallible + ?Sized,
52{
53  fn deserialize_with(field: &A::Archived, d: &mut D) -> Result<T, D::Error> {
54    Ok(T::from_inner(A::deserialize_with(field, d)?))
55  }
56}
57
58// for Arc
59impl<T> AsInnerConverter for std::sync::Arc<T> {
60  type Inner = T;
61  fn to_inner(&self) -> &Self::Inner {
62    self.as_ref()
63  }
64  fn from_inner(data: Self::Inner) -> Self {
65    Self::new(data)
66  }
67}
68
69// for OnceCell
70// rkyv::with::Map
71#[repr(u8)]
72enum ArchivedOptionTag {
73  None,
74  Some,
75}
76#[repr(C)]
77struct ArchivedOptionVariantNone(ArchivedOptionTag);
78#[repr(C)]
79struct ArchivedOptionVariantSome<T>(ArchivedOptionTag, T);
80
81// SAFETY: `ArchivedOptionTag` is `repr(u8)` and so always consists of a single
82// well-defined byte.
83unsafe impl NoUndef for ArchivedOptionTag {}
84
85impl<O, A> ArchiveWith<once_cell::sync::OnceCell<O>> for AsInner<A>
86where
87  A: ArchiveWith<O>,
88{
89  type Archived = ArchivedOption<<A as ArchiveWith<O>>::Archived>;
90  type Resolver = Option<<A as ArchiveWith<O>>::Resolver>;
91
92  fn resolve_with(
93    field: &once_cell::sync::OnceCell<O>,
94    resolver: Self::Resolver,
95    out: Place<Self::Archived>,
96  ) {
97    // port rkyv::with::Map
98    match resolver {
99      None => {
100        let out = unsafe { out.cast_unchecked::<ArchivedOptionVariantNone>() };
101        munge!(let ArchivedOptionVariantNone(tag) = out);
102        tag.write(ArchivedOptionTag::None);
103      }
104      Some(resolver) => {
105        let out = unsafe {
106          out.cast_unchecked::<ArchivedOptionVariantSome<<A as ArchiveWith<O>>::Archived>>()
107        };
108        munge!(let ArchivedOptionVariantSome(tag, out_value) = out);
109        tag.write(ArchivedOptionTag::Some);
110
111        let value = if let Some(value) = field.get() {
112          value
113        } else {
114          unsafe {
115            core::hint::unreachable_unchecked();
116          }
117        };
118
119        A::resolve_with(value, resolver, out_value);
120      }
121    }
122  }
123}
124
125impl<A, O, S> SerializeWith<once_cell::sync::OnceCell<O>, S> for AsInner<A>
126where
127  S: Fallible + ?Sized,
128  A: ArchiveWith<O> + SerializeWith<O, S>,
129{
130  fn serialize_with(
131    field: &once_cell::sync::OnceCell<O>,
132    s: &mut S,
133  ) -> Result<Self::Resolver, S::Error> {
134    Ok(match field.get() {
135      Some(inner) => Some(A::serialize_with(inner, s)?),
136      None => None,
137    })
138  }
139}
140
141impl<A, O, D>
142  DeserializeWith<ArchivedOption<<A as ArchiveWith<O>>::Archived>, once_cell::sync::OnceCell<O>, D>
143  for AsInner<A>
144where
145  D: Fallible + ?Sized,
146  A: ArchiveWith<O> + DeserializeWith<<A as ArchiveWith<O>>::Archived, O, D>,
147{
148  fn deserialize_with(
149    field: &ArchivedOption<<A as ArchiveWith<O>>::Archived>,
150    d: &mut D,
151  ) -> Result<once_cell::sync::OnceCell<O>, D::Error> {
152    match field {
153      ArchivedOption::Some(value) => Ok(once_cell::sync::OnceCell::with_value(
154        A::deserialize_with(value, d)?,
155      )),
156      ArchivedOption::None => Ok(once_cell::sync::OnceCell::new()),
157    }
158  }
159}