Skip to main content

qp_trie/
entry.rs

1use core::borrow::Borrow;
2use core::marker::PhantomData;
3use core::mem;
4
5use unreachable::UncheckedOptionExt;
6
7use node::{Leaf, Node};
8use util::nybble_get_mismatch;
9
10pub fn make_entry<'a, K: 'a + Borrow<[u8]>, V: 'a>(
11    key: K,
12    root: &'a mut Option<Node<K, V>>,
13    count: &'a mut usize,
14) -> Entry<'a, K, V> {
15    match *root {
16        Some(..) => Entry::nonempty(key, root, count),
17        None => Entry::empty(key, root, count),
18    }
19}
20
21/// An entry - occupied or vacant - in the trie, corresponding to some given key.
22#[derive(Debug)]
23pub enum Entry<'a, K: 'a, V: 'a> {
24    Vacant(VacantEntry<'a, K, V>),
25    Occupied(OccupiedEntry<'a, K, V>),
26}
27
28impl<'a, K: 'a + Borrow<[u8]>, V: 'a> Entry<'a, K, V> {
29    fn nonempty(key: K, root: &'a mut Option<Node<K, V>>, count: &'a mut usize) -> Entry<'a, K, V> {
30        let (exemplar_ptr, mismatch) = {
31            let node = unsafe { root.as_mut().unchecked_unwrap() };
32            let exemplar = node.get_exemplar_mut(key.borrow());
33            let mismatch = nybble_get_mismatch(exemplar.key_slice(), key.borrow());
34            (exemplar as *mut Leaf<K, V>, mismatch)
35        };
36
37        match mismatch {
38            None => Entry::occupied(exemplar_ptr, root as *mut Option<Node<K, V>>, count),
39
40            Some((b, i)) => {
41                let node = unsafe { root.as_mut().unchecked_unwrap() };
42
43                Entry::vacant_nonempty(key, i, b, node, count)
44            }
45        }
46    }
47
48    fn occupied(
49        leaf: *mut Leaf<K, V>,
50        root: *mut Option<Node<K, V>>,
51        count: &'a mut usize,
52    ) -> Entry<'a, K, V> {
53        Entry::Occupied(OccupiedEntry {
54            _dummy: PhantomData,
55            leaf,
56            root,
57            count,
58        })
59    }
60
61    fn vacant_nonempty(
62        key: K,
63        graft: usize,
64        graft_nybble: u8,
65        node: &'a mut Node<K, V>,
66        count: &'a mut usize,
67    ) -> Entry<'a, K, V> {
68        Entry::Vacant(VacantEntry {
69            key,
70            inner: VacantEntryInner::Internal(graft, graft_nybble, node),
71            count,
72        })
73    }
74
75    fn empty(key: K, root: &'a mut Option<Node<K, V>>, count: &'a mut usize) -> Entry<'a, K, V> {
76        Entry::Vacant(VacantEntry {
77            key,
78            inner: VacantEntryInner::Root(root),
79            count,
80        })
81    }
82
83    /// Get a mutable reference to a value already in the trie, if it exists - otherwise, insert a
84    /// given default value, and return a mutable reference to its new location in the trie.
85    pub fn or_insert(self, default: V) -> &'a mut V {
86        match self {
87            Entry::Vacant(vacant) => vacant.insert(default),
88            Entry::Occupied(occupied) => occupied.into_mut(),
89        }
90    }
91
92    /// Get a mutable reference to a value already in the trie, if it exists - otherwise, call the
93    /// provided closure to construct a new value, insert it into the trie, and then return a
94    /// mutable reference to it.
95    pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
96        match self {
97            Entry::Vacant(vacant) => vacant.insert(default()),
98            Entry::Occupied(occupied) => occupied.into_mut(),
99        }
100    }
101
102    /// Get a reference to the key associated with this entry.
103    pub fn key(&self) -> &K {
104        match self {
105            Entry::Vacant(vacant) => vacant.key(),
106            Entry::Occupied(occupied) => occupied.key(),
107        }
108    }
109}
110
111/// A vacant entry in the trie.
112#[derive(Debug)]
113pub struct VacantEntry<'a, K: 'a, V: 'a> {
114    key: K,
115    inner: VacantEntryInner<'a, K, V>,
116    count: &'a mut usize,
117}
118
119#[derive(Debug)]
120enum VacantEntryInner<'a, K: 'a, V: 'a> {
121    Root(&'a mut Option<Node<K, V>>),
122    Internal(usize, u8, &'a mut Node<K, V>),
123}
124
125impl<'a, K: 'a + Borrow<[u8]>, V: 'a> VacantEntry<'a, K, V> {
126    /// Get a reference to the key associated with this vacant entry.
127    pub fn key(&self) -> &K {
128        &self.key
129    }
130
131    /// Consume the vacant entry to produce the associated key.
132    pub fn into_key(self) -> K {
133        self.key
134    }
135
136    /// Insert a value into the vacant entry, returning a mutable reference to the newly inserted
137    /// value.
138    pub fn insert(self, val: V) -> &'a mut V {
139        *self.count += 1;
140        match self.inner {
141            VacantEntryInner::Root(root) => {
142                debug_assert!(root.is_none());
143
144                *root = Some(Node::Leaf(Leaf::new(self.key, val)));
145                let root_mut_opt = root.as_mut();
146                let leaf_mut = unsafe { root_mut_opt.unchecked_unwrap().unwrap_leaf_mut() };
147                &mut leaf_mut.val
148            }
149            VacantEntryInner::Internal(graft, graft_nybble, node) => {
150                node.insert_with_graft_point(graft, graft_nybble, self.key, val)
151            }
152        }
153    }
154}
155
156/// An occupied entry in the trie.
157#[derive(Debug)]
158pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
159    _dummy: PhantomData<&'a mut ()>,
160
161    leaf: *mut Leaf<K, V>,
162    root: *mut Option<Node<K, V>>,
163    count: &'a mut usize,
164}
165
166impl<'a, K: 'a + Borrow<[u8]>, V: 'a> OccupiedEntry<'a, K, V> {
167    /// Get a reference to the key of the entry.
168    pub fn key(&self) -> &K {
169        let leaf = unsafe { &*self.leaf };
170        &leaf.key
171    }
172
173    /// Remove the entry from the trie, returning the stored key and value.
174    pub fn remove_entry(self) -> (K, V) {
175        let root = unsafe { &mut *self.root };
176        *self.count -= 1;
177        match *root {
178            Some(Node::Leaf(_)) => {
179                let leaf_opt = root.take();
180                let leaf = unsafe { leaf_opt.unchecked_unwrap().unwrap_leaf() };
181
182                debug_assert!(leaf.key_slice() == self.key().borrow());
183                (leaf.key, leaf.val)
184            }
185
186            Some(Node::Branch(_)) => {
187                let branch_opt = root.as_mut();
188                let branch = unsafe { branch_opt.unchecked_unwrap() };
189
190                let leaf_opt = branch.remove_validated(self.key().borrow());
191
192                debug_assert!(leaf_opt.is_some());
193                let leaf = unsafe { leaf_opt.unchecked_unwrap() };
194
195                (leaf.key, leaf.val)
196            }
197
198            None => unsafe { debug_unreachable!() },
199        }
200    }
201
202    /// Get a reference to the value in the occupied entry.
203    pub fn get(&self) -> &V {
204        let leaf = unsafe { &*self.leaf };
205        &leaf.val
206    }
207
208    /// Get a mutable reference to the value in the occupied entry.
209    pub fn get_mut(&mut self) -> &mut V {
210        let leaf = unsafe { &mut *self.leaf };
211        &mut leaf.val
212    }
213
214    /// Consume the entry to produce a mutable reference to the associated value.
215    pub fn into_mut(self) -> &'a mut V {
216        let leaf = unsafe { &mut *self.leaf };
217        &mut leaf.val
218    }
219
220    /// Replace the associated value, returning the old one.
221    pub fn insert(&mut self, val: V) -> V {
222        let leaf = unsafe { &mut *self.leaf };
223        mem::replace(&mut leaf.val, val)
224    }
225
226    /// Remove the entry altogether, returning the previously stored value.
227    pub fn remove(self) -> V {
228        self.remove_entry().1
229    }
230}