1use std::ops::Deref;
2
3use once_cell::sync::OnceCell;
4
5#[derive(Clone, Debug)]
7pub struct CacheCell<T>(OnceCell<T>);
8
9impl<T> Deref for CacheCell<T> {
10 type Target = OnceCell<T>;
11
12 fn deref(&self) -> &Self::Target {
13 &self.0
14 }
15}
16
17impl<T> CacheCell<T> {
18 pub fn new() -> Self {
19 Self(OnceCell::new())
20 }
21}
22
23impl<T> From<T> for CacheCell<T> {
24 fn from(value: T) -> Self {
25 Self(OnceCell::from(value))
26 }
27}
28
29impl<T> Default for CacheCell<T> {
30 fn default() -> Self {
31 Self::new()
32 }
33}
34
35#[cfg(feature = "rkyv-impl")]
36mod 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 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}