Skip to content

Commit

Permalink
feat: add slices to keys implementations
Browse files Browse the repository at this point in the history
Prior to this commit, we provided implementations only for `Vec`.
However, the exact same implementation can be easily extended to slices,
as both types are almost transparent.

This commit introduces such implementation. It will allow the user to
query a radix tree that has a key of integers as key, using a slice of
integers. That is possible because the get fucntion will accept anything
that the key borrows to, and vec borrows to slice natively.
  • Loading branch information
vlopes11 committed Mar 6, 2023
1 parent 4618661 commit 5bfb306
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 31 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ categories = ["data-structures", "text-processing"]

[dependencies]
nibble_vec = "0.1"
endian-type = "0.1.2"
endian-type = "0.2.0"
serde = { version = "1.0", optional = true }

[dev-dependencies]
Expand Down
4 changes: 2 additions & 2 deletions src/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl<'a, K, V> Iter<'a, K, V> {
// TODO: make this private somehow (and same for the other iterators).
pub fn new(root: &'a TrieNode<K, V>) -> Iter<'a, K, V> {
Iter {
root: root,
root,
root_visited: false,
stack: vec![],
}
Expand Down Expand Up @@ -105,7 +105,7 @@ impl<'a, K, V> Iterator for Children<'a, K, V> {
fn next(&mut self) -> Option<SubTrie<'a, K, V>> {
self.inner.next().map(|node| SubTrie {
prefix: self.prefix.clone().join(&node.key),
node: node,
node,
})
}
}
Expand Down
34 changes: 24 additions & 10 deletions src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,18 +131,14 @@ impl<'a, T: ?Sized + TrieKey> TrieKey for &'a mut T {
impl TrieKey for i8 {
#[inline]
fn encode_bytes(&self) -> Vec<u8> {
let mut v: Vec<u8> = Vec::with_capacity(1);
v.push(*self as u8);
v
vec![*self as u8]
}
}

impl TrieKey for u8 {
#[inline]
fn encode_bytes(&self) -> Vec<u8> {
let mut v: Vec<u8> = Vec::with_capacity(1);
v.push(*self);
v
vec![*self]
}
}

Expand All @@ -168,7 +164,7 @@ where
T: Eq + Copy,
{
fn encode_bytes(&self) -> Vec<u8> {
self.as_bytes().encode_bytes()
self.as_byte_slice().encode_bytes()
}
}

Expand All @@ -177,7 +173,7 @@ where
T: Eq + Copy,
{
fn encode_bytes(&self) -> Vec<u8> {
self.as_bytes().to_vec()
self.as_byte_slice().to_vec()
}
}

Expand All @@ -194,7 +190,7 @@ macro_rules! int_keys {
};
}

int_keys!(u16, u32, u64, i16, i32, i64, usize, isize);
int_keys!(u16, u32, u64, u128, i16, i32, i64, i128, usize, isize);

macro_rules! vec_int_keys {
( $( $t:ty ),* ) => {
Expand All @@ -212,7 +208,25 @@ macro_rules! vec_int_keys {
};
}

vec_int_keys!(u16, u32, u64, i16, i32, i64, usize, isize);
vec_int_keys!(u16, u32, u64, u128, i16, i32, i64, i128, usize, isize);

macro_rules! slice_int_keys {
( $( $t:ty ),* ) => {
$(
impl TrieKey for [$t] {
fn encode_bytes(&self) -> Vec<u8> {
let mut v = Vec::<u8>::with_capacity(self.len() * std::mem::size_of::<$t>());
for u in self {
v.extend_from_slice(&u.to_be_bytes());
}
v
}
}
)*
};
}

slice_int_keys!(u16, u32, u64, u128, i16, i32, i64, i128, usize, isize);

#[cfg(test)]
mod test {
Expand Down
10 changes: 5 additions & 5 deletions src/traversal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ fn iterative_insert<K, V>(trie: &mut TrieNode<K, V>, key: K, value: V, mut nv: N
where
K: TrieKey,
{
if nv.len() == 0 {
if nv.is_empty() {
return trie.replace_value(key, value);
}

Expand Down Expand Up @@ -155,7 +155,7 @@ where
{
let nv = key.encode();

if nv.len() == 0 {
if nv.is_empty() {
return trie.take_value(key);
}

Expand Down Expand Up @@ -273,7 +273,7 @@ fn get_ancestor<'a, K, V>(
where
K: TrieKey,
{
if nv.len() == 0 {
if nv.is_empty() {
return trie.as_value_node().map(|node| (node, 0));
}

Expand Down Expand Up @@ -313,7 +313,7 @@ fn get_raw_ancestor<'a, K, V>(trie: &'a TrieNode<K, V>, nv: &Nibblet) -> (&'a Tr
where
K: TrieKey,
{
if nv.len() == 0 {
if nv.is_empty() {
return (trie, 0);
}

Expand Down Expand Up @@ -357,7 +357,7 @@ fn get_raw_descendant<'a, K, V>(
trie: &'a TrieNode<K, V>,
nv: &Nibblet,
) -> Option<DescendantResult<'a, K, V>> {
if nv.len() == 0 {
if nv.is_empty() {
return Some(NoModification(trie));
}

Expand Down
20 changes: 7 additions & 13 deletions src/trie_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,7 @@ where
pub fn with_key_value(key_fragments: Nibblet, key: K, value: V) -> TrieNode<K, V> {
TrieNode {
key: key_fragments,
key_value: Some(Box::new(KeyValue {
key: key,
value: value,
})),
key_value: Some(Box::new(KeyValue { key, value })),
children: Default::default(),
child_count: 0,
}
Expand Down Expand Up @@ -216,18 +213,15 @@ where
// Insert the collected items below what is now an empty prefix node.
let bucket = key.get(0) as usize;
self.children[bucket] = Some(Box::new(TrieNode {
key: key,
key,
key_value,
children,
child_count,
}));
}
#[inline]
pub fn as_subtrie(&self, prefix: Nibblet) -> SubTrie<K, V> {
SubTrie {
prefix: prefix,
node: self,
}
SubTrie { prefix, node: self }
}
#[inline]
pub fn as_subtrie_mut<'a>(
Expand All @@ -236,8 +230,8 @@ where
length: &'a mut usize,
) -> SubTrieMut<'a, K, V> {
SubTrieMut {
prefix: prefix,
length: length,
prefix,
length,
node: self,
}
}
Expand All @@ -247,7 +241,7 @@ where
/// or false and a junk value if any test fails.
pub fn check_integrity_recursive(&self, prefix: &Nibblet) -> (bool, usize) {
let mut sub_tree_size = 0;
let is_root = prefix.len() == 0;
let is_root = prefix.is_empty();

// Check that no value-less, non-root nodes have only 1 child.
if !is_root && self.child_count == 1 && self.key_value.is_none() {
Expand All @@ -256,7 +250,7 @@ where
}

// Check that all non-root key vector's have length > 1.
if !is_root && self.key.len() == 0 {
if !is_root && self.key.is_empty() {
println!("Key length is 0 at non-root node.");
return (false, sub_tree_size);
}
Expand Down

0 comments on commit 5bfb306

Please sign in to comment.