Skip to main content

fast_cache/storage/embedded_store_shared/
guards.rs

1use super::*;
2
3/// Borrowed value guard returned by [`SharedEmbeddedStore::get`].
4///
5/// The value slice is valid while this guard is alive.
6///
7/// ```compile_fail
8/// use fast_cache::storage::{SharedEmbeddedConfig, SharedEmbeddedStore};
9///
10/// let store = SharedEmbeddedStore::<4>::new(SharedEmbeddedConfig::default());
11/// store.insert_slice(b"k", b"v");
12/// let value = store.get(b"k").unwrap();
13///
14/// fn require_send<T: Send>(_: T) {}
15/// require_send(value);
16/// ```
17pub struct Ref<'a> {
18    pub(super) guard: SharedReadGuard<'a, EmbeddedShard>,
19    pub(super) value: *const [u8],
20    pub(super) _not_send: PhantomData<*const ()>,
21}
22
23impl Ref<'_> {
24    /// Returns the borrowed value bytes.
25    #[inline(always)]
26    pub fn value(&self) -> &[u8] {
27        let _guard = &self.guard;
28        // SAFETY: `value` points into `guard`'s shard, and the read guard is
29        // held for this `Ref`'s full lifetime.
30        unsafe { &*self.value }
31    }
32}
33
34impl Deref for Ref<'_> {
35    type Target = [u8];
36
37    #[inline(always)]
38    fn deref(&self) -> &Self::Target {
39        self.value()
40    }
41}
42
43/// Mutable point-key guard returned by [`SharedEmbeddedStore::get_mut`].
44pub struct RefMut<'a> {
45    pub(super) guard: SharedWriteGuard<'a, EmbeddedShard>,
46    pub(super) route_mode: EmbeddedRouteMode,
47    pub(super) key: SharedBytes,
48    pub(super) key_hash: u64,
49    pub(super) _not_send: PhantomData<*const ()>,
50}
51
52impl RefMut<'_> {
53    /// Returns the current value bytes when the key is still present.
54    #[inline(always)]
55    pub fn value(&self) -> Option<&[u8]> {
56        self.guard
57            .get_ref_hashed_shared_no_ttl(self.key_hash, self.key.as_ref())
58    }
59
60    /// Replaces the value without changing the key.
61    #[inline(always)]
62    pub fn set(&mut self, value: SharedBytes) {
63        self.guard.set_value_bytes_hashed_no_ttl(
64            self.route_mode,
65            self.key_hash,
66            self.key.as_ref(),
67            value,
68        );
69    }
70
71    /// Removes the entry and returns the stored bytes when present.
72    #[inline(always)]
73    pub fn remove(mut self) -> Option<SharedBytes> {
74        self.guard
75            .remove_value_hashed_no_ttl(self.key_hash, self.key.as_ref())
76    }
77}
78
79/// Occupied or vacant routed entry.
80pub enum Entry<'a> {
81    /// Existing point-key value.
82    Occupied(RefMut<'a>),
83    /// Missing point-key value.
84    Vacant(VacantEntry<'a>),
85}
86
87impl<'a> Entry<'a> {
88    /// Inserts `value` when vacant and returns a mutable guard either way.
89    #[inline(always)]
90    pub fn or_insert(self, value: SharedBytes) -> RefMut<'a> {
91        match self {
92            Self::Occupied(entry) => entry,
93            Self::Vacant(entry) => entry.insert(value),
94        }
95    }
96}
97
98/// Vacant routed entry.
99pub struct VacantEntry<'a> {
100    pub(super) guard: SharedWriteGuard<'a, EmbeddedShard>,
101    pub(super) route_mode: EmbeddedRouteMode,
102    pub(super) key: SharedBytes,
103    pub(super) key_hash: u64,
104    pub(super) _not_send: PhantomData<*const ()>,
105}
106
107impl<'a> VacantEntry<'a> {
108    /// Inserts `value` and returns a mutable guard for the new entry.
109    #[inline(always)]
110    pub fn insert(mut self, value: SharedBytes) -> RefMut<'a> {
111        self.guard.set_value_bytes_hashed_no_ttl(
112            self.route_mode,
113            self.key_hash,
114            self.key.as_ref(),
115            value,
116        );
117        RefMut {
118            guard: self.guard,
119            route_mode: self.route_mode,
120            key: self.key,
121            key_hash: self.key_hash,
122            _not_send: PhantomData,
123        }
124    }
125}