/rust/registry/src/index.crates.io-1949cf8c6b5b557f/swc_common-17.0.1/src/cache.rs
Line | Count | Source |
1 | | use std::ops::Deref; |
2 | | |
3 | | use once_cell::sync::OnceCell; |
4 | | |
5 | | /// Wrapper for [OnceCell] with support for [rkyv]. |
6 | | #[derive(Clone, Debug)] |
7 | | pub struct CacheCell<T>(OnceCell<T>); |
8 | | |
9 | | impl<T> Deref for CacheCell<T> { |
10 | | type Target = OnceCell<T>; |
11 | | |
12 | 0 | fn deref(&self) -> &Self::Target { |
13 | 0 | &self.0 |
14 | 0 | } |
15 | | } |
16 | | |
17 | | impl<T> CacheCell<T> { |
18 | 0 | pub fn new() -> Self { |
19 | 0 | Self(OnceCell::new()) |
20 | 0 | } |
21 | | } |
22 | | |
23 | | impl<T> From<T> for CacheCell<T> { |
24 | 0 | fn from(value: T) -> Self { |
25 | 0 | Self(OnceCell::from(value)) |
26 | 0 | } |
27 | | } |
28 | | |
29 | | impl<T> Default for CacheCell<T> { |
30 | 0 | fn default() -> Self { |
31 | 0 | Self::new() |
32 | 0 | } |
33 | | } |
34 | | |
35 | | #[cfg(feature = "rkyv-impl")] |
36 | | mod rkyv_impl { |
37 | | use std::hint::unreachable_unchecked; |
38 | | |
39 | | use rancor::Fallible; |
40 | | use rkyv::{ |
41 | | munge::munge, option::ArchivedOption, traits::NoUndef, Archive, Deserialize, Place, |
42 | | Serialize, |
43 | | }; |
44 | | |
45 | | use super::*; |
46 | | |
47 | | #[allow(dead_code)] |
48 | | #[repr(u8)] |
49 | | enum ArchivedOptionTag { |
50 | | None, |
51 | | Some, |
52 | | } |
53 | | |
54 | | // SAFETY: `ArchivedOptionTag` is `repr(u8)` and so always consists of a single |
55 | | // well-defined byte. |
56 | | unsafe impl NoUndef for ArchivedOptionTag {} |
57 | | |
58 | | #[repr(C)] |
59 | | struct ArchivedOptionVariantNone(ArchivedOptionTag); |
60 | | |
61 | | #[repr(C)] |
62 | | struct ArchivedOptionVariantSome<T>(ArchivedOptionTag, T); |
63 | | |
64 | | impl<T: Archive> Archive for CacheCell<T> { |
65 | | type Archived = ArchivedOption<T::Archived>; |
66 | | type Resolver = Option<T::Resolver>; |
67 | | |
68 | | fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) { |
69 | | match resolver { |
70 | | None => { |
71 | | let out = unsafe { out.cast_unchecked::<ArchivedOptionVariantNone>() }; |
72 | | munge!(let ArchivedOptionVariantNone(tag) = out); |
73 | | tag.write(ArchivedOptionTag::None); |
74 | | } |
75 | | Some(resolver) => { |
76 | | let out = |
77 | | unsafe { out.cast_unchecked::<ArchivedOptionVariantSome<T::Archived>>() }; |
78 | | munge!(let ArchivedOptionVariantSome(tag, out_value) = out); |
79 | | tag.write(ArchivedOptionTag::Some); |
80 | | |
81 | | let value = if let Some(value) = self.get() { |
82 | | value |
83 | | } else { |
84 | | unsafe { |
85 | | unreachable_unchecked(); |
86 | | } |
87 | | }; |
88 | | |
89 | | value.resolve(resolver, out_value); |
90 | | } |
91 | | } |
92 | | } |
93 | | } |
94 | | |
95 | | impl<T: Serialize<S>, S: Fallible + ?Sized> Serialize<S> for CacheCell<T> { |
96 | | fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> { |
97 | | self.get() |
98 | | .map(|value| value.serialize(serializer)) |
99 | | .transpose() |
100 | | } |
101 | | } |
102 | | |
103 | | impl<T, D> Deserialize<CacheCell<T>, D> for ArchivedOption<T::Archived> |
104 | | where |
105 | | T: Archive, |
106 | | T::Archived: Deserialize<T, D>, |
107 | | D: Fallible + ?Sized, |
108 | | { |
109 | | fn deserialize(&self, deserializer: &mut D) -> Result<CacheCell<T>, D::Error> { |
110 | | Ok(match self { |
111 | | ArchivedOption::Some(value) => CacheCell::from(value.deserialize(deserializer)?), |
112 | | ArchivedOption::None => CacheCell::new(), |
113 | | }) |
114 | | } |
115 | | } |
116 | | } |