radix_trie/
traversal.rs

1//! This module contains the core algorithms.
2
3use crate::keys::{match_keys, KeyMatch};
4use crate::TrieKey;
5use crate::TrieNode;
6use std::borrow::Borrow;
7
8use nibble_vec::Nibblet;
9
10use self::DescendantResult::*;
11
12impl<K, V> TrieNode<K, V>
13where
14    K: TrieKey,
15{
16    #[inline]
17    pub fn get(&self, nv: &Nibblet) -> Option<&TrieNode<K, V>> {
18        iterative_get(self, nv)
19    }
20    #[inline]
21    pub fn get_mut(&mut self, nv: &Nibblet) -> Option<&mut TrieNode<K, V>> {
22        iterative_get_mut(self, nv)
23    }
24    #[inline]
25    pub fn insert(&mut self, key: K, value: V, nv: Nibblet) -> Option<V> {
26        iterative_insert(self, key, value, nv)
27    }
28    #[inline]
29    pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
30    where
31        K: Borrow<Q>,
32        Q: TrieKey,
33    {
34        recursive_remove(self, key)
35    }
36    #[inline]
37    pub fn get_ancestor(&self, nv: &Nibblet) -> Option<(&TrieNode<K, V>, usize)> {
38        get_ancestor(self, nv)
39    }
40    #[inline]
41    pub fn get_raw_ancestor(&self, nv: &Nibblet) -> (&TrieNode<K, V>, usize) {
42        get_raw_ancestor(self, nv)
43    }
44    #[inline]
45    pub fn get_raw_descendant<'a>(&'a self, nv: &Nibblet) -> Option<DescendantResult<'a, K, V>> {
46        get_raw_descendant(self, nv)
47    }
48}
49
50macro_rules! get_func {
51    (
52        name: $name:ident,
53        trie_type: $trie_type:ty,
54        mutability: $($mut_:tt)*
55    ) => {id!{
56        #[inline]
57        fn $name<'a, K, V>(trie: $trie_type, nv: &Nibblet) -> Option<$trie_type> {
58            if nv.len() == 0 {
59                return Some(trie);
60            }
61
62            let mut prev = trie;
63            let mut depth = 0;
64
65            loop {
66                let bucket = nv.get(depth) as usize;
67                let current = prev;
68                if let Some(ref $($mut_)* child) = current.children[bucket] {
69                    match match_keys(depth, nv, &child.key) {
70                        KeyMatch::Full => {
71                            return Some(child);
72                        }
73                        KeyMatch::SecondPrefix => {
74                            depth += child.key.len();
75                            prev = child;
76                        }
77                        _ => {
78                            return None;
79                        }
80                    }
81                } else {
82                    return None;
83                }
84            }
85        }
86    }}
87}
88
89get_func!(name: iterative_get, trie_type: &'a TrieNode<K, V>, mutability: );
90get_func!(name: iterative_get_mut, trie_type: &'a mut TrieNode<K, V>, mutability: mut);
91
92#[inline]
93fn iterative_insert<K, V>(trie: &mut TrieNode<K, V>, key: K, value: V, mut nv: Nibblet) -> Option<V>
94where
95    K: TrieKey,
96{
97    if nv.len() == 0 {
98        return trie.replace_value(key, value);
99    }
100
101    let mut prev = trie;
102    let mut depth = 0;
103
104    loop {
105        let bucket = nv.get(depth) as usize;
106        let current = prev;
107        if let Some(ref mut child) = current.children[bucket] {
108            match match_keys(depth, &nv, &child.key) {
109                KeyMatch::Full => {
110                    return child.replace_value(key, value);
111                }
112                KeyMatch::Partial(idx) => {
113                    // Split the existing child.
114                    child.split(idx);
115
116                    // Insert the new key below the prefix node.
117                    let new_key = nv.split(depth + idx);
118                    let new_key_bucket = new_key.get(0) as usize;
119
120                    child.add_child(
121                        new_key_bucket,
122                        Box::new(TrieNode::with_key_value(new_key, key, value)),
123                    );
124
125                    return None;
126                }
127                KeyMatch::FirstPrefix => {
128                    child.split(nv.len() - depth);
129                    child.add_key_value(key, value);
130                    return None;
131                }
132                KeyMatch::SecondPrefix => {
133                    depth += child.key.len();
134                    prev = child;
135                }
136            }
137        } else {
138            let node_key = nv.split(depth);
139            current.add_child(
140                bucket,
141                Box::new(TrieNode::with_key_value(node_key, key, value)),
142            );
143            return None;
144        }
145    }
146}
147
148// TODO: clean this up and make it iterative.
149#[inline]
150fn recursive_remove<K, Q: ?Sized, V>(trie: &mut TrieNode<K, V>, key: &Q) -> Option<V>
151where
152    K: TrieKey,
153    K: Borrow<Q>,
154    Q: TrieKey,
155{
156    let nv = key.encode();
157
158    if nv.len() == 0 {
159        return trie.take_value(key);
160    }
161
162    let bucket = nv.get(0) as usize;
163
164    let child = trie.take_child(bucket);
165
166    match child {
167        Some(mut child) => {
168            match match_keys(0, &nv, &child.key) {
169                KeyMatch::Full => {
170                    let result = child.take_value(key);
171                    if child.child_count != 0 {
172                        // If removing this node's value has made it a value-less node with a
173                        // single child, then merge its child.
174                        let repl = if child.child_count == 1 {
175                            get_merge_child(&mut child)
176                        } else {
177                            child
178                        };
179                        trie.add_child(bucket, repl);
180                    }
181                    result
182                }
183                KeyMatch::SecondPrefix => {
184                    let depth = child.key.len();
185                    rec_remove(trie, child, bucket, key, depth, &nv)
186                }
187                KeyMatch::FirstPrefix | KeyMatch::Partial(_) => {
188                    trie.add_child(bucket, child);
189                    None
190                }
191            }
192        }
193        None => None,
194    }
195}
196#[inline]
197fn get_merge_child<K, V>(trie: &mut TrieNode<K, V>) -> Box<TrieNode<K, V>>
198where
199    K: TrieKey,
200{
201    let mut child = trie.take_only_child();
202
203    // Join the child's key onto the existing one.
204    child.key = trie.key.clone().join(&child.key);
205
206    child
207}
208
209// Tail-recursive remove function used by `recursive_remove`.
210#[inline]
211fn rec_remove<K, Q: ?Sized, V>(
212    parent: &mut TrieNode<K, V>,
213    mut middle: Box<TrieNode<K, V>>,
214    prev_bucket: usize,
215    key: &Q,
216    depth: usize,
217    nv: &Nibblet,
218) -> Option<V>
219where
220    K: TrieKey,
221    K: Borrow<Q>,
222    Q: TrieKey,
223{
224    let bucket = nv.get(depth) as usize;
225
226    let child = middle.take_child(bucket);
227    parent.add_child(prev_bucket, middle);
228
229    match child {
230        Some(mut child) => {
231            let middle = parent.children[prev_bucket].as_mut().unwrap();
232            match match_keys(depth, nv, &child.key) {
233                KeyMatch::Full => {
234                    let result = child.take_value(key);
235
236                    // If this node has children, keep it.
237                    if child.child_count != 0 {
238                        // If removing this node's value has made it a value-less node with a
239                        // single child, then merge its child.
240                        let repl = if child.child_count == 1 {
241                            get_merge_child(&mut *child)
242                        } else {
243                            child
244                        };
245                        middle.add_child(bucket, repl);
246                    }
247                    // Otherwise, if the parent node now only has a single child, merge it.
248                    else if middle.child_count == 1 && middle.key_value.is_none() {
249                        let repl = get_merge_child(middle);
250                        *middle = repl;
251                    }
252
253                    result
254                }
255                KeyMatch::SecondPrefix => {
256                    let new_depth = depth + child.key.len();
257                    rec_remove(middle, child, bucket, key, new_depth, nv)
258                }
259                KeyMatch::FirstPrefix | KeyMatch::Partial(_) => {
260                    middle.add_child(bucket, child);
261                    None
262                }
263            }
264        }
265        None => None,
266    }
267}
268#[inline]
269fn get_ancestor<'a, K, V>(
270    trie: &'a TrieNode<K, V>,
271    nv: &Nibblet,
272) -> Option<(&'a TrieNode<K, V>, usize)>
273where
274    K: TrieKey,
275{
276    if nv.len() == 0 {
277        return trie.as_value_node().map(|node| (node, 0));
278    }
279
280    let mut prev = trie;
281    // The ancestor is such that all nodes upto and including `prev` have
282    // already been considered.
283    let mut ancestor = prev.as_value_node();
284    let mut depth = 0;
285
286    loop {
287        let bucket = nv.get(depth) as usize;
288        let current = prev;
289        if let Some(ref child) = current.children[bucket] {
290            match match_keys(depth, nv, &child.key) {
291                KeyMatch::Full => {
292                    return child
293                        .as_value_node()
294                        .map(|node| (node, depth + node.key.len()))
295                        .or_else(|| ancestor.map(|anc| (anc, depth)));
296                }
297                KeyMatch::FirstPrefix | KeyMatch::Partial(_) => {
298                    return ancestor.map(|anc| (anc, depth));
299                }
300                KeyMatch::SecondPrefix => {
301                    depth += child.key.len();
302                    ancestor = child.as_value_node().or(ancestor);
303                    prev = child;
304                }
305            }
306        } else {
307            return ancestor.map(|anc| (anc, depth));
308        }
309    }
310}
311#[inline]
312fn get_raw_ancestor<'a, K, V>(trie: &'a TrieNode<K, V>, nv: &Nibblet) -> (&'a TrieNode<K, V>, usize)
313where
314    K: TrieKey,
315{
316    if nv.len() == 0 {
317        return (trie, 0);
318    }
319
320    let mut prev = trie;
321    // The ancestor is such that all nodes upto and including `prev` have
322    // already been considered.
323    let mut ancestor = prev;
324    let mut depth = 0;
325
326    loop {
327        let bucket = nv.get(depth) as usize;
328        let current = prev;
329        if let Some(ref child) = current.children[bucket] {
330            match match_keys(depth, nv, &child.key) {
331                KeyMatch::Full => {
332                    return (child, depth + child.key.len());
333                }
334                KeyMatch::FirstPrefix | KeyMatch::Partial(_) => {
335                    return (ancestor, depth);
336                }
337                KeyMatch::SecondPrefix => {
338                    depth += child.key.len();
339                    ancestor = child;
340                    prev = child;
341                }
342            }
343        } else {
344            return (ancestor, depth);
345        }
346    }
347}
348
349// Type used to propogate subtrie construction instructions to the top-level `get_raw_descendant`
350// method.
351pub enum DescendantResult<'a, K: 'a, V: 'a> {
352    NoModification(&'a TrieNode<K, V>),
353    ExtendKey(&'a TrieNode<K, V>, usize, &'a Nibblet),
354}
355#[inline]
356fn get_raw_descendant<'a, K, V>(
357    trie: &'a TrieNode<K, V>,
358    nv: &Nibblet,
359) -> Option<DescendantResult<'a, K, V>> {
360    if nv.len() == 0 {
361        return Some(NoModification(trie));
362    }
363
364    let mut prev = trie;
365    let mut depth = 0;
366
367    loop {
368        let bucket = nv.get(depth) as usize;
369        let current = prev;
370        if let Some(ref child) = current.children[bucket] {
371            match match_keys(depth, nv, &child.key) {
372                KeyMatch::Full => {
373                    return Some(NoModification(child));
374                }
375                KeyMatch::FirstPrefix => {
376                    return Some(ExtendKey(child, depth, &child.key));
377                }
378                KeyMatch::SecondPrefix => {
379                    depth += child.key.len();
380                    prev = child;
381                }
382                _ => {
383                    return None;
384                }
385            }
386        } else {
387            return None;
388        }
389    }
390}