Skip to content

Upgrade to Rust 2021 #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
authors = ["Sean Leffler <[email protected]>"]
name = "qp-trie"
version = "0.8.2"

edition = "2021"
description = "An idiomatic and fast QP-trie implementation in pure Rust, written with an emphasis on safety."

documentation = "https://docs.rs/qp-trie"
Expand All @@ -21,14 +21,13 @@ license = "MPL-2.0"
travis-ci = { repository = "sdleffler/qp-trie-rs", branch = "master" }

[dependencies]
new_debug_unreachable = "1.0.1"
serde = { version = "1.0.11", optional = true, features = ["derive"] }
unreachable = "1.0.0"
new_debug_unreachable = "1.0.4"
serde = { version = "1.0", optional = true, features = ["derive"] }

[dev-dependencies]
bincode = "1.0"
fnv = "1.0.5"
fnv = "1.0.7"
qptrie = "0.2.2"
quickcheck = "0.9"
rand = "0.7"
serde_json = "1.0.3"
quickcheck = "1.0.3"
rand = "0.8"
serde_json = "1.0"
18 changes: 8 additions & 10 deletions src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ use core::borrow::Borrow;
use core::marker::PhantomData;
use core::mem;

use unreachable::UncheckedOptionExt;

use node::{Leaf, Node};
use util::nybble_get_mismatch;
use crate::node::{Leaf, Node};
use crate::util::nybble_get_mismatch;

pub fn make_entry<'a, K: 'a + Borrow<[u8]>, V: 'a>(
key: K,
Expand All @@ -28,7 +26,7 @@ pub enum Entry<'a, K: 'a, V: 'a> {
impl<'a, K: 'a + Borrow<[u8]>, V: 'a> Entry<'a, K, V> {
fn nonempty(key: K, root: &'a mut Option<Node<K, V>>, count: &'a mut usize) -> Entry<'a, K, V> {
let (exemplar_ptr, mismatch) = {
let node = unsafe { root.as_mut().unchecked_unwrap() };
let node = unsafe { root.as_mut().unwrap_unchecked() };
let exemplar = node.get_exemplar_mut(key.borrow());
let mismatch = nybble_get_mismatch(exemplar.key_slice(), key.borrow());
(exemplar as *mut Leaf<K, V>, mismatch)
Expand All @@ -38,7 +36,7 @@ impl<'a, K: 'a + Borrow<[u8]>, V: 'a> Entry<'a, K, V> {
None => Entry::occupied(exemplar_ptr, root as *mut Option<Node<K, V>>, count),

Some((b, i)) => {
let node = unsafe { root.as_mut().unchecked_unwrap() };
let node = unsafe { root.as_mut().unwrap_unchecked() };

Entry::vacant_nonempty(key, i, b, node, count)
}
Expand Down Expand Up @@ -143,7 +141,7 @@ impl<'a, K: 'a + Borrow<[u8]>, V: 'a> VacantEntry<'a, K, V> {

*root = Some(Node::Leaf(Leaf::new(self.key, val)));
let root_mut_opt = root.as_mut();
let leaf_mut = unsafe { root_mut_opt.unchecked_unwrap().unwrap_leaf_mut() };
let leaf_mut = unsafe { root_mut_opt.unwrap_unchecked().unwrap_leaf_mut() };
&mut leaf_mut.val
}
VacantEntryInner::Internal(graft, graft_nybble, node) => {
Expand Down Expand Up @@ -177,20 +175,20 @@ impl<'a, K: 'a + Borrow<[u8]>, V: 'a> OccupiedEntry<'a, K, V> {
match *root {
Some(Node::Leaf(_)) => {
let leaf_opt = root.take();
let leaf = unsafe { leaf_opt.unchecked_unwrap().unwrap_leaf() };
let leaf = unsafe { leaf_opt.unwrap_unchecked().unwrap_leaf() };

debug_assert!(leaf.key_slice() == self.key().borrow());
(leaf.key, leaf.val)
}

Some(Node::Branch(_)) => {
let branch_opt = root.as_mut();
let branch = unsafe { branch_opt.unchecked_unwrap() };
let branch = unsafe { branch_opt.unwrap_unchecked() };

let leaf_opt = branch.remove_validated(self.key().borrow());

debug_assert!(leaf_opt.is_some());
let leaf = unsafe { leaf_opt.unchecked_unwrap() };
let leaf = unsafe { leaf_opt.unwrap_unchecked() };

(leaf.key, leaf.val)
}
Expand Down
2 changes: 1 addition & 1 deletion src/iter.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use alloc::{vec, vec::Vec};

use node::Node;
use crate::node::Node;

/// An iterator over the keys and values in a QP-trie.
#[derive(Clone, Debug)]
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ extern crate alloc;

#[macro_use]
extern crate debug_unreachable;
extern crate unreachable;

#[cfg(feature = "serde")]
#[macro_use]
Expand Down
46 changes: 20 additions & 26 deletions src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ use core::borrow::Borrow;
use core::fmt;
use core::mem;

use unreachable::UncheckedOptionExt;

use iter::{IntoIter, Iter, IterMut};
use sparse::Sparse;
use util::{nybble_index, nybble_mismatch};
use crate::iter::{IntoIter, Iter, IterMut};
use crate::sparse::Sparse;
use crate::util::{nybble_index, nybble_mismatch};

// A leaf in the trie.
#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -82,27 +80,26 @@ impl<K: Borrow<[u8]>, V> Branch<K, V> {
pub fn entry_mut(&mut self, index: u8) -> &mut Node<K, V> {
let entry = self.entries.get_mut(index);
debug_assert!(entry.is_some());
unsafe { entry.unchecked_unwrap() }
unsafe { entry.unwrap_unchecked() }
}

// Get the child node corresponding to the given key.
#[inline]
pub fn child(&self, key: &[u8]) -> Option<&Node<K, V>> {
self.entries.get(nybble_index(self.choice, key.borrow()))
self.entries.get(nybble_index(self.choice, key))
}

// Mutable version of `Branch::child`.
#[inline]
pub fn child_mut(&mut self, key: &[u8]) -> Option<&mut Node<K, V>> {
self.entries
.get_mut(nybble_index(self.choice, key.borrow()))
self.entries.get_mut(nybble_index(self.choice, key))
}

// Immutably borrow the leaf for the given key, if it exists, mutually recursing through
// `Node::get`.
#[inline]
pub fn get(&self, key: &[u8]) -> Option<&Leaf<K, V>> {
match self.child(key.borrow()) {
match self.child(key) {
Some(child) => child.get(key),
None => None,
}
Expand All @@ -112,37 +109,34 @@ impl<K: Borrow<[u8]>, V> Branch<K, V> {
// `Node::get_mut`.
#[inline]
pub fn get_mut(&mut self, key: &[u8]) -> Option<&mut Leaf<K, V>> {
self.child_mut(key.borrow())
.and_then(|node| node.get_mut(key))
self.child_mut(key).and_then(|node| node.get_mut(key))
}

// Retrieve the node which contains the exemplar. This does not recurse and return the actual
// exemplar - just the node which might be or contain it.
#[inline]
pub fn exemplar(&self, key: &[u8]) -> &Node<K, V> {
self.entries
.get_or_any(nybble_index(self.choice, key.borrow()))
self.entries.get_or_any(nybble_index(self.choice, key))
}

// As `Branch::exemplar` but for mutable borrows.
#[inline]
pub fn exemplar_mut(&mut self, key: &[u8]) -> &mut Node<K, V> {
self.entries
.get_or_any_mut(nybble_index(self.choice, key.borrow()))
self.entries.get_or_any_mut(nybble_index(self.choice, key))
}

// Immutably borrow the exemplar for the given key, mutually recursing through
// `Node::get_exemplar`.
#[inline]
pub fn get_exemplar(&self, key: &[u8]) -> &Leaf<K, V> {
self.exemplar(key.borrow()).get_exemplar(key)
self.exemplar(key).get_exemplar(key)
}

// Mutably borrow the exemplar for the given key, mutually recursing through
// `Node::get_exemplar_mut`.
#[inline]
pub fn get_exemplar_mut(&mut self, key: &[u8]) -> &mut Leaf<K, V> {
self.exemplar_mut(key.borrow()).get_exemplar_mut(key)
self.exemplar_mut(key).get_exemplar_mut(key)
}

// Convenience method for inserting a leaf into the branch's sparse array.
Expand Down Expand Up @@ -336,7 +330,7 @@ impl<K: Borrow<[u8]>, V> Node<K, V> {
let child_opt = branch.child(prefix);

// unsafe: child must exist in the trie - prefix'd nodes must exist.
let child = unsafe { child_opt.unchecked_unwrap() };
let child = unsafe { child_opt.unwrap_unchecked() };

child.get_prefix_validated(prefix)
}
Expand Down Expand Up @@ -379,7 +373,7 @@ impl<K: Borrow<[u8]>, V> Node<K, V> {

// unsafe: child must exist as there must exist nodes with the given prefix in
// the trie.
let child = unsafe { child_opt.unchecked_unwrap() };
let child = unsafe { child_opt.unwrap_unchecked() };

child.get_prefix_validated_mut(prefix)
}
Expand Down Expand Up @@ -565,11 +559,11 @@ impl<K: Borrow<[u8]>, V> Node<K, V> {
match *root {
Some(Node::Leaf(..))
// unsafe: root has been match'd as some branch.
if unsafe { root.as_ref().unchecked_unwrap().unwrap_leaf_ref() }
if unsafe { root.as_ref().unwrap_unchecked().unwrap_leaf_ref() }
.key_slice() == key => {

// unsafe: same rationale.
Some(unsafe { root.take().unchecked_unwrap().unwrap_leaf() })
Some(unsafe { root.take().unwrap_unchecked().unwrap_leaf() })
}

Some(ref mut node @ Node::Branch(..)) => node.remove_validated(key),
Expand Down Expand Up @@ -627,24 +621,24 @@ impl<K: Borrow<[u8]>, V> Node<K, V> {
match *root {
Some(Node::Leaf(..))
// unsafe: root has been matched as some leaf.
if unsafe { root.as_ref().unchecked_unwrap().unwrap_leaf_ref() }
if unsafe { root.as_ref().unwrap_unchecked().unwrap_leaf_ref() }
.key_slice()
.starts_with(prefix) => root.take(),

Some(Node::Branch(..))
// unsafe: root has been matched as some branch.
if unsafe { root.as_ref().unchecked_unwrap().unwrap_branch_ref() }
if unsafe { root.as_ref().unwrap_unchecked().unwrap_branch_ref() }
.get_exemplar(prefix)
.key_slice()
.starts_with(prefix) => {

// unsafe: same rationale.
if unsafe { root.as_ref().unchecked_unwrap().unwrap_branch_ref() }
if unsafe { root.as_ref().unwrap_unchecked().unwrap_branch_ref() }
.choice >= prefix.len() * 2
{
root.take()
} else {
unsafe { root.as_mut().unchecked_unwrap() }.remove_prefix_validated(prefix)
unsafe { root.as_mut().unwrap_unchecked() }.remove_prefix_validated(prefix)
}
}

Expand Down
4 changes: 1 addition & 3 deletions src/sparse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ use alloc::vec::{IntoIter, Vec};
use core::fmt;
use core::slice::{Iter, IterMut};

use unreachable::UncheckedOptionExt;

// A sparse array, holding up to 17 elements, indexed by nybbles with a special exception for
// elements which are shorter than the "choice point" of the branch node which holds this sparse
// array. This special exception is the "head".
Expand Down Expand Up @@ -120,7 +118,7 @@ impl<T> Sparse<T> {
#[inline]
pub fn clear_last(&mut self) -> T {
debug_assert!(self.len() == 1);
unsafe { self.entries.pop().unchecked_unwrap() }
unsafe { self.entries.pop().unwrap_unchecked() }
}

#[inline]
Expand Down
4 changes: 2 additions & 2 deletions src/subtrie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use core::borrow::Borrow;
use core::fmt;
use core::ops::Index;

use iter::Iter;
use node::Node;
use crate::iter::Iter;
use crate::node::Node;

pub struct SubTrie<'a, K: 'a, V: 'a> {
pub(crate) root: Option<&'a Node<K, V>>,
Expand Down
12 changes: 6 additions & 6 deletions src/trie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ use core::fmt;
use core::iter::FromIterator;
use core::ops::{Index, IndexMut};

use entry::{make_entry, Entry};
use iter::{IntoIter, Iter, IterMut, Keys, Values, ValuesMut};
use node::{Leaf, Node};
use subtrie::SubTrie;
use util::nybble_mismatch;
use wrapper::{BStr, BString};
use crate::entry::{make_entry, Entry};
use crate::iter::{IntoIter, Iter, IterMut, Keys, Values, ValuesMut};
use crate::node::{Leaf, Node};
use crate::subtrie::SubTrie;
use crate::util::nybble_mismatch;
use crate::wrapper::{BStr, BString};

/// A QP-trie. QP stands for - depending on who you ask - either "quelques-bits popcount" or
/// "quad-bit popcount". In any case, the fact of the matter is that this is a compressed radix
Expand Down
2 changes: 1 addition & 1 deletion src/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use core::fmt;
use core::hash::{Hash, Hasher};
use core::ops::Deref;

use trie::Break;
use crate::trie::Break;

/// A wrapper for `String` which implements `Borrow<[u8]>` and hashes in the same way as a byte
/// slice.
Expand Down