Coverage Report

Created: 2026-11-11 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}