Line data Source code
1 : use std::ops::{Deref, DerefMut};
2 :
3 : /// A generic trait which exposes types of cache's key and value,
4 : /// as well as the notion of cache entry invalidation.
5 : /// This is useful for [`Cached`].
6 : pub(crate) trait Cache {
7 : /// Entry's key.
8 : type Key;
9 :
10 : /// Entry's value.
11 : type Value;
12 :
13 : /// Used for entry invalidation.
14 : type LookupInfo<Key>;
15 :
16 : /// Invalidate an entry using a lookup info.
17 : /// We don't have an empty default impl because it's error-prone.
18 : fn invalidate(&self, _: &Self::LookupInfo<Self::Key>);
19 : }
20 :
21 : impl<C: Cache> Cache for &C {
22 : type Key = C::Key;
23 : type Value = C::Value;
24 : type LookupInfo<Key> = C::LookupInfo<Key>;
25 :
26 4 : fn invalidate(&self, info: &Self::LookupInfo<Self::Key>) {
27 4 : C::invalidate(self, info);
28 4 : }
29 : }
30 :
31 : /// Wrapper for convenient entry invalidation.
32 : pub(crate) struct Cached<C: Cache, V = <C as Cache>::Value> {
33 : /// Cache + lookup info.
34 : pub(crate) token: Option<(C, C::LookupInfo<C::Key>)>,
35 :
36 : /// The value itself.
37 : pub(crate) value: V,
38 : }
39 :
40 : impl<C: Cache, V> Cached<C, V> {
41 : /// Place any entry into this wrapper; invalidation will be a no-op.
42 12 : pub(crate) fn new_uncached(value: V) -> Self {
43 12 : Self { token: None, value }
44 12 : }
45 :
46 3 : pub(crate) fn take_value(self) -> (Cached<C, ()>, V) {
47 3 : (
48 3 : Cached {
49 3 : token: self.token,
50 3 : value: (),
51 3 : },
52 3 : self.value,
53 3 : )
54 3 : }
55 :
56 10 : pub(crate) fn map<U>(self, f: impl FnOnce(V) -> U) -> Cached<C, U> {
57 10 : Cached {
58 10 : token: self.token,
59 10 : value: f(self.value),
60 10 : }
61 10 : }
62 :
63 : /// Drop this entry from a cache if it's still there.
64 5 : pub(crate) fn invalidate(self) -> V {
65 5 : if let Some((cache, info)) = &self.token {
66 4 : cache.invalidate(info);
67 4 : }
68 5 : self.value
69 5 : }
70 :
71 : /// Tell if this entry is actually cached.
72 18 : pub(crate) fn cached(&self) -> bool {
73 18 : self.token.is_some()
74 18 : }
75 : }
76 :
77 : impl<C: Cache, V> Deref for Cached<C, V> {
78 : type Target = V;
79 :
80 3 : fn deref(&self) -> &Self::Target {
81 3 : &self.value
82 3 : }
83 : }
84 :
85 : impl<C: Cache, V> DerefMut for Cached<C, V> {
86 26 : fn deref_mut(&mut self) -> &mut Self::Target {
87 26 : &mut self.value
88 26 : }
89 : }
|