Skip to content

Commit

Permalink
Merge pull request #39 from sile/get-longest-common-prefix-len
Browse files Browse the repository at this point in the history
Add {PatriciaMap,PatriciaSet}::longest_common_prefix_len() methods
  • Loading branch information
sile authored Dec 10, 2023
2 parents 6d0d7c0 + c62b2a4 commit 5ed5f1b
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 1 deletion.
26 changes: 26 additions & 0 deletions src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,32 @@ impl<K: Bytes, V> GenericPatriciaMap<K, V> {
Some((K::Borrowed::from_bytes(key), value))
}

/// Returns the longest common prefix length of `key` and the keys in this map.
///
/// Unlike `get_longest_common_prefix()`, this method does not check if there is a key that matches the prefix in this map.
///
/// # Examples
///
/// ```
/// use patricia_tree::PatriciaMap;
///
/// let mut map = PatriciaMap::new();
/// map.insert("foo", 1);
/// map.insert("foobar", 2);
/// assert_eq!(map.longest_common_prefix_len("fo"), 2);
/// assert_eq!(map.longest_common_prefix_len("foo"), 3);
/// assert_eq!(map.longest_common_prefix_len("fooba"), 5);
/// assert_eq!(map.longest_common_prefix_len("foobar"), 6);
/// assert_eq!(map.longest_common_prefix_len("foobarbaz"), 6);
/// assert_eq!(map.longest_common_prefix_len("foba"), 2);
/// ```
pub fn longest_common_prefix_len<Q>(&self, key: &Q) -> usize
where
Q: ?Sized + AsRef<K::Borrowed>,
{
self.tree.longest_common_prefix_len(key.as_ref())
}

/// Inserts a key-value pair into this map.
///
/// If the map did not have this key present, `None` is returned.
Expand Down
24 changes: 23 additions & 1 deletion src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,29 @@ impl<V> Node<V> {
None
}
}

pub(crate) fn longest_common_prefix_len<K: ?Sized + BorrowedBytes>(
&self,
key: &K,
offset: usize,
) -> usize {
let (next, common_prefix_len) = key.strip_common_prefix_and_len(self.label());
let next_offset = offset + common_prefix_len;
if common_prefix_len == self.label().len() {
if next.is_empty() {
next_offset
} else {
self.child()
.map(|child| child.longest_common_prefix_len(next, next_offset))
.unwrap_or(next_offset)
}
} else if common_prefix_len == 0 && key.cmp_first_item(self.label()).is_ge() {
self.sibling()
.map(|sibling| sibling.longest_common_prefix_len(next, offset))
.unwrap_or(next_offset)
} else {
next_offset
}
}
pub(crate) fn get_longest_common_prefix<K: ?Sized + BorrowedBytes>(
&self,
key: &K,
Expand Down
26 changes: 26 additions & 0 deletions src/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,32 @@ impl<T: Bytes> GenericPatriciaSet<T> {
self.map.get_longest_common_prefix(value).map(|x| x.0)
}

/// Returns the longest common prefix length of `value` and the elements in this set.
///
/// Unlike `get_longest_common_prefix()`, this method does not check if there is a element that matches the prefix in this set.
///
/// # Examples
///
/// ```
/// use patricia_tree::PatriciaSet;
///
/// let mut set = PatriciaSet::new();
/// set.insert("foo");
/// set.insert("foobar");
/// assert_eq!(set.longest_common_prefix_len("fo"), 2);
/// assert_eq!(set.longest_common_prefix_len("foo"), 3);
/// assert_eq!(set.longest_common_prefix_len("fooba"), 5);
/// assert_eq!(set.longest_common_prefix_len("foobar"), 6);
/// assert_eq!(set.longest_common_prefix_len("foobarbaz"), 6);
/// assert_eq!(set.longest_common_prefix_len("foba"), 2);
/// ```
pub fn longest_common_prefix_len<U>(&self, value: &U) -> usize
where
U: ?Sized + AsRef<T::Borrowed>,
{
self.map.longest_common_prefix_len(value)
}

/// Adds a value to this set.
///
/// If the set did not have this value present, `true` is returned.
Expand Down
3 changes: 3 additions & 0 deletions src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ impl<V> PatriciaTree<V> {
pub fn get_mut<K: ?Sized + BorrowedBytes>(&mut self, key: &K) -> Option<&mut V> {
self.root.get_mut(key)
}
pub fn longest_common_prefix_len<K: ?Sized + BorrowedBytes>(&self, key: &K) -> usize {
self.root.longest_common_prefix_len(key, 0)
}
pub fn get_longest_common_prefix<'a, K: ?Sized + BorrowedBytes>(
&self,
key: &'a K,
Expand Down

0 comments on commit 5ed5f1b

Please sign in to comment.