1use std::sync::Arc;
4
5use hitbox::backend::CacheBackend;
6use hitbox::concurrency::NoopConcurrencyManager;
7use hitbox::policy::PolicyConfig;
8use hitbox_core::DisabledOffload;
9
10pub struct NoBackend;
12
13pub struct NoPolicy;
15
16pub struct NoContext;
18
19pub struct WithContext;
21
22pub struct WithBackend<B>(pub Arc<B>);
24
25pub struct WithPolicy(pub Arc<PolicyConfig>);
27
28pub struct Cache<B, CM = NoopConcurrencyManager, O = DisabledOffload> {
63 pub(crate) backend: Arc<B>,
64 pub(crate) policy: Arc<PolicyConfig>,
65 pub(crate) concurrency_manager: CM,
66 pub(crate) offload: O,
67}
68
69impl<B, CM, O> Cache<B, CM, O> {
70 pub fn backend(&self) -> &Arc<B> {
72 &self.backend
73 }
74
75 pub fn policy(&self) -> &Arc<PolicyConfig> {
77 &self.policy
78 }
79
80 pub fn concurrency_manager(&self) -> &CM {
82 &self.concurrency_manager
83 }
84
85 pub fn offload(&self) -> &O {
87 &self.offload
88 }
89}
90
91pub trait CacheAccess {
96 type Backend;
98 type ConcurrencyManager;
100 type Offload;
102
103 fn backend(&self) -> Arc<Self::Backend>;
105 fn policy(&self) -> Arc<PolicyConfig>;
107 fn concurrency_manager(&self) -> Self::ConcurrencyManager;
109 fn offload(&self) -> Self::Offload;
111}
112
113impl<B, CM: Clone, O: Clone> CacheAccess for Cache<B, CM, O> {
114 type Backend = B;
115 type ConcurrencyManager = CM;
116 type Offload = O;
117
118 fn backend(&self) -> Arc<B> {
119 Arc::clone(&self.backend)
120 }
121 fn policy(&self) -> Arc<PolicyConfig> {
122 Arc::clone(&self.policy)
123 }
124 fn concurrency_manager(&self) -> CM {
125 self.concurrency_manager.clone()
126 }
127 fn offload(&self) -> O {
128 self.offload.clone()
129 }
130}
131
132impl<T: CacheAccess> CacheAccess for &T {
133 type Backend = T::Backend;
134 type ConcurrencyManager = T::ConcurrencyManager;
135 type Offload = T::Offload;
136
137 fn backend(&self) -> Arc<Self::Backend> {
138 (**self).backend()
139 }
140 fn policy(&self) -> Arc<PolicyConfig> {
141 (**self).policy()
142 }
143 fn concurrency_manager(&self) -> Self::ConcurrencyManager {
144 (**self).concurrency_manager()
145 }
146 fn offload(&self) -> Self::Offload {
147 (**self).offload()
148 }
149}
150
151impl<T: CacheAccess> CacheAccess for Arc<T> {
152 type Backend = T::Backend;
153 type ConcurrencyManager = T::ConcurrencyManager;
154 type Offload = T::Offload;
155
156 fn backend(&self) -> Arc<Self::Backend> {
157 (**self).backend()
158 }
159 fn policy(&self) -> Arc<PolicyConfig> {
160 (**self).policy()
161 }
162 fn concurrency_manager(&self) -> Self::ConcurrencyManager {
163 (**self).concurrency_manager()
164 }
165 fn offload(&self) -> Self::Offload {
166 (**self).offload()
167 }
168}
169
170impl<B, CM: Clone, O: Clone> Clone for Cache<B, CM, O> {
171 fn clone(&self) -> Self {
172 Self {
173 backend: Arc::clone(&self.backend),
174 policy: Arc::clone(&self.policy),
175 concurrency_manager: self.concurrency_manager.clone(),
176 offload: self.offload.clone(),
177 }
178 }
179}
180
181impl Cache<(), NoopConcurrencyManager, DisabledOffload> {
182 pub fn builder() -> CacheBuilder<NoBackend, NoPolicy, NoopConcurrencyManager, DisabledOffload> {
184 CacheBuilder {
185 backend: NoBackend,
186 policy: NoPolicy,
187 concurrency_manager: NoopConcurrencyManager,
188 offload: DisabledOffload,
189 }
190 }
191}
192
193pub struct CacheBuilder<B, P, CM, O> {
198 pub(crate) backend: B,
199 pub(crate) policy: P,
200 pub(crate) concurrency_manager: CM,
201 pub(crate) offload: O,
202}
203
204impl<P, CM, O> CacheBuilder<NoBackend, P, CM, O> {
205 pub fn backend<B: CacheBackend>(self, backend: B) -> CacheBuilder<WithBackend<B>, P, CM, O> {
214 CacheBuilder {
215 backend: WithBackend(Arc::new(backend)),
216 policy: self.policy,
217 concurrency_manager: self.concurrency_manager,
218 offload: self.offload,
219 }
220 }
221}
222
223impl<B, CM, O> CacheBuilder<B, NoPolicy, CM, O> {
224 pub fn policy(self, policy: PolicyConfig) -> CacheBuilder<B, WithPolicy, CM, O> {
233 CacheBuilder {
234 backend: self.backend,
235 policy: WithPolicy(Arc::new(policy)),
236 concurrency_manager: self.concurrency_manager,
237 offload: self.offload,
238 }
239 }
240}
241
242impl<B, P, CM, O> CacheBuilder<B, P, CM, O> {
243 pub fn concurrency_manager<CM2>(self, cm: CM2) -> CacheBuilder<B, P, CM2, O> {
261 CacheBuilder {
262 backend: self.backend,
263 policy: self.policy,
264 concurrency_manager: cm,
265 offload: self.offload,
266 }
267 }
268
269 pub fn offload<O2>(self, offload: O2) -> CacheBuilder<B, P, CM, O2> {
287 CacheBuilder {
288 backend: self.backend,
289 policy: self.policy,
290 concurrency_manager: self.concurrency_manager,
291 offload,
292 }
293 }
294}
295
296impl<B, CM, O> CacheBuilder<WithBackend<B>, WithPolicy, CM, O>
297where
298 B: CacheBackend,
299{
300 pub fn build(self) -> Cache<B, CM, O> {
304 Cache {
305 backend: self.backend.0,
306 policy: self.policy.0,
307 concurrency_manager: self.concurrency_manager,
308 offload: self.offload,
309 }
310 }
311}