rspack_cacheable/with/
as_inner.rs1use 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
58impl<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#[repr(u8)]
72enum ArchivedOptionTag {
73 None,
74 Some,
75}
76#[repr(C)]
77struct ArchivedOptionVariantNone(ArchivedOptionTag);
78#[repr(C)]
79struct ArchivedOptionVariantSome<T>(ArchivedOptionTag, T);
80
81unsafe 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 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}