reslab/
entry.rs

1use std::{hash::BuildHasher, ops::Deref};
2
3use dashmap::{
4    mapref::entry::{
5        Entry as DashEntry,
6        OccupiedEntry as DashOccupiedEntry,
7        VacantEntry as DashVacantEntry,
8    },
9    DashMap,
10};
11use sharded_slab::{Entry as SlabEntry, Slab};
12
13use crate::{Index, Key};
14
15/// A type that represents an entry in a slab.
16pub enum Entry<'a, K: Key, V, S> {
17    Vacant(VacantEntry<'a, K, V, S>),
18    Occupied(OccupiedEntry<'a, K, V, S>),
19}
20
21/// A type that represents a vacant entry in a slab.
22pub struct VacantEntry<'a, K: Key, V, S> {
23    idxs: DashVacantEntry<'a, K, usize, S>,
24    slab: &'a Slab<V>,
25}
26
27/// A type that represents an occupied entry in a slab.
28pub struct OccupiedEntry<'a, K: Key, V, S> {
29    idxs_entry: DashOccupiedEntry<'a, K, usize, S>,
30    slab_entry: SlabEntry<'a, V>,
31}
32
33impl<'a, K: Key, V, S> Entry<'a, K, V, S>
34where
35    S: BuildHasher + Clone,
36{
37    /// Creates a new instance of [`Entry`] from the provided key.
38    pub(super) fn new(
39        key: K,
40        idxs: &'a DashMap<K, usize, S>,
41        slab: &'a Slab<V>,
42    ) -> Self {
43        match idxs.entry(key) {
44            | DashEntry::Vacant(e) => Self::Vacant(VacantEntry::new(e, slab)),
45            | DashEntry::Occupied(e) => {
46                let slab_entry = slab.get(*e.get()).expect(
47                    "BUG: slab entries should always exists if the index \
48                     exists in the index map",
49                );
50
51                Self::Occupied(OccupiedEntry::new(e, slab_entry))
52            }
53        }
54    }
55
56    /// Tries to insert the provided value into the slab, returning the
57    /// [`Some(Index<T>)`] of the inserted value if successful.
58    #[inline]
59    pub fn or_try_insert(self, value: V) -> Option<Index<K, V>> {
60        match self {
61            | Self::Occupied(entry) => Some(entry.index()),
62            | Self::Vacant(entry) => entry.try_insert(value),
63        }
64    }
65
66    /// Tries to insert the value returned by the provided closure into the
67    /// slab, returning the [`Some(Index<T>)`] of the inserted value if
68    /// successful.
69    #[inline]
70    pub fn or_try_insert_with(
71        self,
72        f: impl FnOnce() -> V,
73    ) -> Option<Index<K, V>> {
74        match self {
75            | Self::Occupied(entry) => Some(entry.index()),
76            | Self::Vacant(entry) => entry.try_insert(f()),
77        }
78    }
79
80    /// Tries to insert a default value of `V` into the slab, returning the
81    /// [`Some(Index<T>)`] of the inserted value if successful.
82    #[inline]
83    pub fn or_try_insert_default(self) -> Option<Index<K, V>>
84    where
85        V: Default,
86    {
87        self.or_try_insert_with(V::default)
88    }
89}
90
91impl<'a, K: Key, V, S> VacantEntry<'a, K, V, S>
92where
93    S: BuildHasher + Clone,
94{
95    /// Creates a new instance of [`VacantEntry`].
96    #[inline]
97    pub(super) const fn new(
98        idxs: DashVacantEntry<'a, K, usize, S>,
99        slab: &'a Slab<V>,
100    ) -> Self {
101        Self { idxs, slab }
102    }
103
104    /// Inserts the provided value into the slab, returning the index of the
105    /// inserted value.
106    #[inline]
107    pub fn try_insert(self, value: V) -> Option<Index<K, V>>
108    where
109        Self: 'a,
110    {
111        let idx = match self.slab.insert(value) {
112            | Some(slab_idx) => self.idxs.insert(slab_idx),
113            | None => return None,
114        };
115
116        Some(Index::new(*idx.key(), *idx.value()))
117    }
118
119    /// Gets the key for this entry.
120    #[inline]
121    pub fn key(&self) -> &K {
122        self.idxs.key()
123    }
124}
125
126impl<'a, K: Key, V, S> OccupiedEntry<'a, K, V, S>
127where
128    S: BuildHasher + Clone,
129{
130    /// Creates a new instance of [`OccupiedEntry`].
131    #[inline]
132    pub(super) const fn new(
133        idxs_entry: DashOccupiedEntry<'a, K, usize, S>,
134        slab_entry: SlabEntry<'a, V>,
135    ) -> Self {
136        Self {
137            idxs_entry,
138            slab_entry,
139        }
140    }
141
142    /// Gets the key for this entry.
143    #[inline]
144    pub fn key(&self) -> &K {
145        self.idxs_entry.key()
146    }
147
148    /// Gets the offset of the value in the slab.
149    #[inline]
150    pub fn offset(&self) -> usize {
151        *self.idxs_entry.get()
152    }
153
154    /// Gets the index of the value in the slab.
155    #[inline]
156    pub fn index(&self) -> Index<K, V> {
157        Index::new(*self.idxs_entry.key(), *self.idxs_entry.get())
158    }
159
160    /// Gets a reference to the value for this entry.
161    #[inline]
162    pub fn get(&self) -> &V {
163        self.slab_entry.deref()
164    }
165
166    /// Removes the link to this entry from the indeces map, returning the
167    /// offset of the value in the slab.
168    ///
169    /// # Safety
170    /// This does not remove the value from the slab. The actual value **must**
171    /// be removed from the slab manually
172    #[inline]
173    pub unsafe fn unlink(self) -> usize {
174        self.idxs_entry.remove()
175    }
176}