rswind/
cache.rs

1use std::collections::BTreeMap;
2
3use derive_more::{Deref, DerefMut};
4use enum_dispatch::enum_dispatch;
5use lazy_static::lazy_static;
6use rustc_hash::FxHashMap as HashMap;
7use smol_str::SmolStr;
8
9use crate::context::CacheKey;
10
11#[enum_dispatch]
12pub trait Cache {
13    fn mark_valid(&mut self, item: SmolStr);
14
15    fn mark_valid_many(&mut self, items: impl IntoIterator<Item = SmolStr>);
16
17    fn mark_invalid(&mut self, item: SmolStr);
18
19    fn mark_invalid_many(&mut self, items: impl IntoIterator<Item = SmolStr>);
20
21    fn store_css(&mut self, key: CacheKey, value: String);
22
23    fn store_extra_css(&mut self, key: CacheKey, value: String);
24
25    fn has_seen(&self, item: &str) -> bool;
26
27    fn extra_css(&self) -> &BTreeMap<CacheKey, String>;
28
29    fn css(&self) -> &BTreeMap<CacheKey, String>;
30}
31
32#[derive(Debug, Default, Deref, DerefMut)]
33pub struct GeneratorCache {
34    pub need_cache: bool,
35    #[deref]
36    #[deref_mut]
37    pub inner: CacheInner,
38    pub state: CacheState,
39}
40
41impl GeneratorCache {
42    pub fn new(state: CacheState) -> Self {
43        let need_cache = state != CacheState::OneShot;
44        Self {
45            need_cache,
46            state,
47            inner: match need_cache {
48                true => CacheInner::Cache(CacheImpl::default()),
49                false => CacheInner::Noop(NoopCache::default()),
50            },
51        }
52    }
53}
54
55#[derive(Debug)]
56#[enum_dispatch(Cache)]
57pub enum CacheInner {
58    Noop(NoopCache),
59    Cache(CacheImpl),
60}
61
62impl Default for CacheInner {
63    fn default() -> Self {
64        Self::Noop(NoopCache::default())
65    }
66}
67
68#[derive(Debug, Default)]
69pub struct CacheImpl {
70    pub css: BTreeMap<CacheKey, String>,
71    pub groups: BTreeMap<CacheKey, String>,
72    pub valid: HashMap<SmolStr, bool>,
73}
74
75#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
76pub enum CacheState {
77    #[default]
78    OneShot,
79    FirstRun,
80    Cached,
81}
82
83impl CacheState {
84    pub fn is_cached(&self) -> bool {
85        matches!(self, Self::Cached)
86    }
87    pub fn mark_cached(&mut self) {
88        if *self == Self::FirstRun {
89            *self = Self::Cached;
90        }
91    }
92}
93
94impl Cache for CacheImpl {
95    fn css(&self) -> &BTreeMap<CacheKey, String> {
96        &self.css
97    }
98
99    fn store_css(&mut self, key: CacheKey, value: String) {
100        self.css.insert(key, value);
101    }
102
103    fn extra_css(&self) -> &BTreeMap<CacheKey, String> {
104        &self.groups
105    }
106
107    fn store_extra_css(&mut self, key: CacheKey, value: String) {
108        self.groups.insert(key, value);
109    }
110
111    fn has_seen(&self, item: &str) -> bool {
112        self.valid.get(item).copied().unwrap_or(false)
113    }
114
115    fn mark_valid(&mut self, item: SmolStr) {
116        self.valid.insert(item, true);
117    }
118
119    fn mark_valid_many(&mut self, items: impl IntoIterator<Item = SmolStr>) {
120        for item in items {
121            self.valid.insert(item, true);
122        }
123    }
124
125    fn mark_invalid(&mut self, item: SmolStr) {
126        self.valid.insert(item, false);
127    }
128
129    fn mark_invalid_many(&mut self, items: impl IntoIterator<Item = SmolStr>) {
130        for item in items {
131            self.valid.insert(item, false);
132        }
133    }
134}
135
136#[derive(Debug, Default)]
137pub struct NoopCache {
138    pub groups: BTreeMap<CacheKey, String>,
139}
140
141lazy_static! {
142    pub static ref EMPTY_MAP: BTreeMap<CacheKey, String> = BTreeMap::default();
143}
144
145impl Cache for NoopCache {
146    fn css(&self) -> &BTreeMap<CacheKey, String> {
147        &EMPTY_MAP
148    }
149
150    fn extra_css(&self) -> &BTreeMap<CacheKey, String> {
151        &self.groups
152    }
153
154    fn store_extra_css(&mut self, key: CacheKey, value: String) {
155        self.groups.insert(key, value);
156    }
157
158    fn has_seen(&self, _: &str) -> bool {
159        false
160    }
161
162    fn mark_valid(&mut self, _: SmolStr) {}
163
164    fn mark_valid_many(&mut self, _: impl IntoIterator<Item = SmolStr>) {}
165
166    fn mark_invalid(&mut self, _: SmolStr) {}
167
168    fn mark_invalid_many(&mut self, _: impl IntoIterator<Item = SmolStr>) {}
169
170    fn store_css(&mut self, _: CacheKey, _: String) {}
171}