Rollup merge of #70111 - Mark-Simulacrum:btree-no-shared, r=cuviper
BTreeMap: remove shared root This replaces the shared root with `Option`s in the BTreeMap code, and then slightly cleans up the node manipulation code taking advantage of the removal of the shared root. I expect that further simplification is possible, but wanted to get this posted for initial review. Note that `BTreeMap::new()` continues to not allocate. Benchmarks seem within the margin of error/unaffected, as expected for an entirely predictable branch. ``` name alloc-bench-a ns/iter alloc-bench-b ns/iter diff ns/iter diff % speedup btree::map::iter_mut_20 20 21 1 5.00% x 0.95 btree::set::clone_100 1,360 1,439 79 5.81% x 0.95 btree::set::clone_100_and_into_iter 1,319 1,434 115 8.72% x 0.92 btree::set::clone_10k 143,515 150,991 7,476 5.21% x 0.95 btree::set::clone_10k_and_clear 142,792 152,916 10,124 7.09% x 0.93 btree::set::clone_10k_and_into_iter 146,019 154,561 8,542 5.85% x 0.94 ```
This commit is contained in:
commit
9d9e3813b2
|
@ -370,12 +370,17 @@ class RustStdBTreeSetPrinter(object):
|
||||||
("(len: %i)" % self.__val.get_wrapped_value()['map']['length']))
|
("(len: %i)" % self.__val.get_wrapped_value()['map']['length']))
|
||||||
|
|
||||||
def children(self):
|
def children(self):
|
||||||
root = self.__val.get_wrapped_value()['map']['root']
|
prev_idx = None
|
||||||
node_ptr = root['node']
|
innermap = GdbValue(self.__val.get_wrapped_value()['map'])
|
||||||
i = 0
|
if innermap.get_wrapped_value()['length'] > 0:
|
||||||
for child in children_of_node(node_ptr, root['height'], False):
|
root = GdbValue(innermap.get_wrapped_value()['root'])
|
||||||
yield (str(i), child)
|
type_name = str(root.type.ty.name).replace('core::option::Option<', '')[:-1]
|
||||||
i = i + 1
|
root = root.get_wrapped_value().cast(gdb.lookup_type(type_name))
|
||||||
|
node_ptr = root['node']
|
||||||
|
i = 0
|
||||||
|
for child in children_of_node(node_ptr, root['height'], False):
|
||||||
|
yield (str(i), child)
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
|
||||||
class RustStdBTreeMapPrinter(object):
|
class RustStdBTreeMapPrinter(object):
|
||||||
|
@ -391,13 +396,16 @@ class RustStdBTreeMapPrinter(object):
|
||||||
("(len: %i)" % self.__val.get_wrapped_value()['length']))
|
("(len: %i)" % self.__val.get_wrapped_value()['length']))
|
||||||
|
|
||||||
def children(self):
|
def children(self):
|
||||||
root = self.__val.get_wrapped_value()['root']
|
if self.__val.get_wrapped_value()['length'] > 0:
|
||||||
node_ptr = root['node']
|
root = GdbValue(self.__val.get_wrapped_value()['root'])
|
||||||
i = 0
|
type_name = str(root.type.ty.name).replace('core::option::Option<', '')[:-1]
|
||||||
for child in children_of_node(node_ptr, root['height'], True):
|
root = root.get_wrapped_value().cast(gdb.lookup_type(type_name))
|
||||||
yield (str(i), child[0])
|
node_ptr = root['node']
|
||||||
yield (str(i), child[1])
|
i = 0
|
||||||
i = i + 1
|
for child in children_of_node(node_ptr, root['height'], True):
|
||||||
|
yield (str(i), child[0])
|
||||||
|
yield (str(i), child[1])
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
|
||||||
class RustStdStringPrinter(object):
|
class RustStdStringPrinter(object):
|
||||||
|
|
|
@ -122,7 +122,7 @@ use UnderflowResult::*;
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct BTreeMap<K, V> {
|
pub struct BTreeMap<K, V> {
|
||||||
root: node::Root<K, V>,
|
root: Option<node::Root<K, V>>,
|
||||||
length: usize,
|
length: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,10 +147,11 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
||||||
{
|
{
|
||||||
match node.force() {
|
match node.force() {
|
||||||
Leaf(leaf) => {
|
Leaf(leaf) => {
|
||||||
let mut out_tree = BTreeMap { root: node::Root::new_leaf(), length: 0 };
|
let mut out_tree = BTreeMap { root: Some(node::Root::new_leaf()), length: 0 };
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut out_node = match out_tree.root.as_mut().force() {
|
let root = out_tree.root.as_mut().unwrap();
|
||||||
|
let mut out_node = match root.as_mut().force() {
|
||||||
Leaf(leaf) => leaf,
|
Leaf(leaf) => leaf,
|
||||||
Internal(_) => unreachable!(),
|
Internal(_) => unreachable!(),
|
||||||
};
|
};
|
||||||
|
@ -169,9 +170,14 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
||||||
}
|
}
|
||||||
Internal(internal) => {
|
Internal(internal) => {
|
||||||
let mut out_tree = clone_subtree(internal.first_edge().descend());
|
let mut out_tree = clone_subtree(internal.first_edge().descend());
|
||||||
|
out_tree.ensure_root_is_owned();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut out_node = out_tree.root.push_level();
|
// Ideally we'd use the return of ensure_root_is_owned
|
||||||
|
// instead of re-unwrapping here but unfortunately that
|
||||||
|
// borrows all of out_tree and we need access to the
|
||||||
|
// length below.
|
||||||
|
let mut out_node = out_tree.root.as_mut().unwrap().push_level();
|
||||||
let mut in_edge = internal.first_edge();
|
let mut in_edge = internal.first_edge();
|
||||||
while let Ok(kv) = in_edge.right_kv() {
|
while let Ok(kv) = in_edge.right_kv() {
|
||||||
let (k, v) = kv.into_kv();
|
let (k, v) = kv.into_kv();
|
||||||
|
@ -190,7 +196,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
||||||
(root, length)
|
(root, length)
|
||||||
};
|
};
|
||||||
|
|
||||||
out_node.push(k, v, subroot);
|
out_node.push(k, v, subroot.unwrap_or_else(|| node::Root::new_leaf()));
|
||||||
out_tree.length += 1 + sublength;
|
out_tree.length += 1 + sublength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,9 +209,9 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
// Ideally we'd call `BTreeMap::new` here, but that has the `K:
|
// Ideally we'd call `BTreeMap::new` here, but that has the `K:
|
||||||
// Ord` constraint, which this method lacks.
|
// Ord` constraint, which this method lacks.
|
||||||
BTreeMap { root: node::Root::shared_empty_root(), length: 0 }
|
BTreeMap { root: None, length: 0 }
|
||||||
} else {
|
} else {
|
||||||
clone_subtree(self.root.as_ref())
|
clone_subtree(self.root.as_ref().unwrap().as_ref())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,14 +277,14 @@ where
|
||||||
type Key = K;
|
type Key = K;
|
||||||
|
|
||||||
fn get(&self, key: &Q) -> Option<&K> {
|
fn get(&self, key: &Q) -> Option<&K> {
|
||||||
match search::search_tree(self.root.as_ref(), key) {
|
match search::search_tree(self.root.as_ref()?.as_ref(), key) {
|
||||||
Found(handle) => Some(handle.into_kv().0),
|
Found(handle) => Some(handle.into_kv().0),
|
||||||
GoDown(_) => None,
|
GoDown(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take(&mut self, key: &Q) -> Option<K> {
|
fn take(&mut self, key: &Q) -> Option<K> {
|
||||||
match search::search_tree(self.root.as_mut(), key) {
|
match search::search_tree(self.root.as_mut()?.as_mut(), key) {
|
||||||
Found(handle) => Some(
|
Found(handle) => Some(
|
||||||
OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData }
|
OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData }
|
||||||
.remove_kv()
|
.remove_kv()
|
||||||
|
@ -290,7 +296,7 @@ where
|
||||||
|
|
||||||
fn replace(&mut self, key: K) -> Option<K> {
|
fn replace(&mut self, key: K) -> Option<K> {
|
||||||
self.ensure_root_is_owned();
|
self.ensure_root_is_owned();
|
||||||
match search::search_tree::<marker::Mut<'_>, K, (), K>(self.root.as_mut(), &key) {
|
match search::search_tree::<marker::Mut<'_>, K, (), K>(self.root.as_mut()?.as_mut(), &key) {
|
||||||
Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)),
|
Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)),
|
||||||
GoDown(handle) => {
|
GoDown(handle) => {
|
||||||
VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData }
|
VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData }
|
||||||
|
@ -344,15 +350,18 @@ pub struct IterMut<'a, K: 'a, V: 'a> {
|
||||||
/// [`BTreeMap`]: struct.BTreeMap.html
|
/// [`BTreeMap`]: struct.BTreeMap.html
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct IntoIter<K, V> {
|
pub struct IntoIter<K, V> {
|
||||||
front: Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
|
front: Option<Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>>,
|
||||||
back: Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
|
back: Option<Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>>,
|
||||||
length: usize,
|
length: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||||
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IntoIter<K, V> {
|
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IntoIter<K, V> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let range = Range { front: self.front.reborrow(), back: self.back.reborrow() };
|
let range = Range {
|
||||||
|
front: self.front.as_ref().map(|f| f.reborrow()),
|
||||||
|
back: self.back.as_ref().map(|b| b.reborrow()),
|
||||||
|
};
|
||||||
f.debug_list().entries(range).finish()
|
f.debug_list().entries(range).finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -417,8 +426,8 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> {
|
||||||
/// [`BTreeMap`]: struct.BTreeMap.html
|
/// [`BTreeMap`]: struct.BTreeMap.html
|
||||||
#[stable(feature = "btree_range", since = "1.17.0")]
|
#[stable(feature = "btree_range", since = "1.17.0")]
|
||||||
pub struct Range<'a, K: 'a, V: 'a> {
|
pub struct Range<'a, K: 'a, V: 'a> {
|
||||||
front: Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
front: Option<Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>>,
|
||||||
back: Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
back: Option<Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||||
|
@ -437,8 +446,8 @@ impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Range<'_, K, V> {
|
||||||
/// [`BTreeMap`]: struct.BTreeMap.html
|
/// [`BTreeMap`]: struct.BTreeMap.html
|
||||||
#[stable(feature = "btree_range", since = "1.17.0")]
|
#[stable(feature = "btree_range", since = "1.17.0")]
|
||||||
pub struct RangeMut<'a, K: 'a, V: 'a> {
|
pub struct RangeMut<'a, K: 'a, V: 'a> {
|
||||||
front: Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
front: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
|
||||||
back: Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
back: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
|
||||||
|
|
||||||
// Be invariant in `K` and `V`
|
// Be invariant in `K` and `V`
|
||||||
_marker: PhantomData<&'a mut (K, V)>,
|
_marker: PhantomData<&'a mut (K, V)>,
|
||||||
|
@ -447,7 +456,10 @@ pub struct RangeMut<'a, K: 'a, V: 'a> {
|
||||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||||
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for RangeMut<'_, K, V> {
|
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for RangeMut<'_, K, V> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let range = Range { front: self.front.reborrow(), back: self.back.reborrow() };
|
let range = Range {
|
||||||
|
front: self.front.as_ref().map(|f| f.reborrow()),
|
||||||
|
back: self.back.as_ref().map(|b| b.reborrow()),
|
||||||
|
};
|
||||||
f.debug_list().entries(range).finish()
|
f.debug_list().entries(range).finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -544,7 +556,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn new() -> BTreeMap<K, V> {
|
pub fn new() -> BTreeMap<K, V> {
|
||||||
BTreeMap { root: node::Root::shared_empty_root(), length: 0 }
|
BTreeMap { root: None, length: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clears the map, removing all elements.
|
/// Clears the map, removing all elements.
|
||||||
|
@ -589,7 +601,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
K: Borrow<Q>,
|
K: Borrow<Q>,
|
||||||
Q: Ord,
|
Q: Ord,
|
||||||
{
|
{
|
||||||
match search::search_tree(self.root.as_ref(), key) {
|
match search::search_tree(self.root.as_ref()?.as_ref(), key) {
|
||||||
Found(handle) => Some(handle.into_kv().1),
|
Found(handle) => Some(handle.into_kv().1),
|
||||||
GoDown(_) => None,
|
GoDown(_) => None,
|
||||||
}
|
}
|
||||||
|
@ -616,7 +628,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
K: Borrow<Q>,
|
K: Borrow<Q>,
|
||||||
Q: Ord,
|
Q: Ord,
|
||||||
{
|
{
|
||||||
match search::search_tree(self.root.as_ref(), k) {
|
match search::search_tree(self.root.as_ref()?.as_ref(), k) {
|
||||||
Found(handle) => Some(handle.into_kv()),
|
Found(handle) => Some(handle.into_kv()),
|
||||||
GoDown(_) => None,
|
GoDown(_) => None,
|
||||||
}
|
}
|
||||||
|
@ -645,7 +657,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
T: Ord,
|
T: Ord,
|
||||||
K: Borrow<T>,
|
K: Borrow<T>,
|
||||||
{
|
{
|
||||||
let front = self.root.as_ref().first_leaf_edge();
|
let front = self.root.as_ref()?.as_ref().first_leaf_edge();
|
||||||
front.right_kv().ok().map(Handle::into_kv)
|
front.right_kv().ok().map(Handle::into_kv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,7 +686,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
T: Ord,
|
T: Ord,
|
||||||
K: Borrow<T>,
|
K: Borrow<T>,
|
||||||
{
|
{
|
||||||
let front = self.root.as_mut().first_leaf_edge();
|
let front = self.root.as_mut()?.as_mut().first_leaf_edge();
|
||||||
if let Ok(kv) = front.right_kv() {
|
if let Ok(kv) = front.right_kv() {
|
||||||
Some(OccupiedEntry {
|
Some(OccupiedEntry {
|
||||||
handle: kv.forget_node_type(),
|
handle: kv.forget_node_type(),
|
||||||
|
@ -708,7 +720,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
T: Ord,
|
T: Ord,
|
||||||
K: Borrow<T>,
|
K: Borrow<T>,
|
||||||
{
|
{
|
||||||
let back = self.root.as_ref().last_leaf_edge();
|
let back = self.root.as_ref()?.as_ref().last_leaf_edge();
|
||||||
back.left_kv().ok().map(Handle::into_kv)
|
back.left_kv().ok().map(Handle::into_kv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,7 +749,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
T: Ord,
|
T: Ord,
|
||||||
K: Borrow<T>,
|
K: Borrow<T>,
|
||||||
{
|
{
|
||||||
let back = self.root.as_mut().last_leaf_edge();
|
let back = self.root.as_mut()?.as_mut().last_leaf_edge();
|
||||||
if let Ok(kv) = back.left_kv() {
|
if let Ok(kv) = back.left_kv() {
|
||||||
Some(OccupiedEntry {
|
Some(OccupiedEntry {
|
||||||
handle: kv.forget_node_type(),
|
handle: kv.forget_node_type(),
|
||||||
|
@ -801,7 +813,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
K: Borrow<Q>,
|
K: Borrow<Q>,
|
||||||
Q: Ord,
|
Q: Ord,
|
||||||
{
|
{
|
||||||
match search::search_tree(self.root.as_mut(), key) {
|
match search::search_tree(self.root.as_mut()?.as_mut(), key) {
|
||||||
Found(handle) => Some(handle.into_kv_mut().1),
|
Found(handle) => Some(handle.into_kv_mut().1),
|
||||||
GoDown(_) => None,
|
GoDown(_) => None,
|
||||||
}
|
}
|
||||||
|
@ -896,7 +908,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
K: Borrow<Q>,
|
K: Borrow<Q>,
|
||||||
Q: Ord,
|
Q: Ord,
|
||||||
{
|
{
|
||||||
match search::search_tree(self.root.as_mut(), key) {
|
match search::search_tree(self.root.as_mut()?.as_mut(), key) {
|
||||||
Found(handle) => Some(
|
Found(handle) => Some(
|
||||||
OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData }
|
OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData }
|
||||||
.remove_entry(),
|
.remove_entry(),
|
||||||
|
@ -992,11 +1004,15 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
K: Borrow<T>,
|
K: Borrow<T>,
|
||||||
R: RangeBounds<T>,
|
R: RangeBounds<T>,
|
||||||
{
|
{
|
||||||
let root1 = self.root.as_ref();
|
if let Some(root) = &self.root {
|
||||||
let root2 = self.root.as_ref();
|
let root1 = root.as_ref();
|
||||||
let (f, b) = range_search(root1, root2, range);
|
let root2 = root.as_ref();
|
||||||
|
let (f, b) = range_search(root1, root2, range);
|
||||||
|
|
||||||
Range { front: f, back: b }
|
Range { front: Some(f), back: Some(b) }
|
||||||
|
} else {
|
||||||
|
Range { front: None, back: None }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a mutable double-ended iterator over a sub-range of elements in the map.
|
/// Constructs a mutable double-ended iterator over a sub-range of elements in the map.
|
||||||
|
@ -1036,11 +1052,15 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
K: Borrow<T>,
|
K: Borrow<T>,
|
||||||
R: RangeBounds<T>,
|
R: RangeBounds<T>,
|
||||||
{
|
{
|
||||||
let root1 = self.root.as_mut();
|
if let Some(root) = &mut self.root {
|
||||||
let root2 = unsafe { ptr::read(&root1) };
|
let root1 = root.as_mut();
|
||||||
let (f, b) = range_search(root1, root2, range);
|
let root2 = unsafe { ptr::read(&root1) };
|
||||||
|
let (f, b) = range_search(root1, root2, range);
|
||||||
|
|
||||||
RangeMut { front: f, back: b, _marker: PhantomData }
|
RangeMut { front: Some(f), back: Some(b), _marker: PhantomData }
|
||||||
|
} else {
|
||||||
|
RangeMut { front: None, back: None, _marker: PhantomData }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the given key's corresponding entry in the map for in-place manipulation.
|
/// Gets the given key's corresponding entry in the map for in-place manipulation.
|
||||||
|
@ -1065,7 +1085,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
|
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
|
||||||
// FIXME(@porglezomp) Avoid allocating if we don't insert
|
// FIXME(@porglezomp) Avoid allocating if we don't insert
|
||||||
self.ensure_root_is_owned();
|
self.ensure_root_is_owned();
|
||||||
match search::search_tree(self.root.as_mut(), &key) {
|
match search::search_tree(self.root.as_mut().unwrap().as_mut(), &key) {
|
||||||
Found(handle) => {
|
Found(handle) => {
|
||||||
Occupied(OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData })
|
Occupied(OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData })
|
||||||
}
|
}
|
||||||
|
@ -1077,7 +1097,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
|
|
||||||
fn from_sorted_iter<I: Iterator<Item = (K, V)>>(&mut self, iter: I) {
|
fn from_sorted_iter<I: Iterator<Item = (K, V)>>(&mut self, iter: I) {
|
||||||
self.ensure_root_is_owned();
|
self.ensure_root_is_owned();
|
||||||
let mut cur_node = self.root.as_mut().last_leaf_edge().into_node();
|
let mut cur_node = self.root.as_mut().unwrap().as_mut().last_leaf_edge().into_node();
|
||||||
// Iterate through all key-value pairs, pushing them into nodes at the right level.
|
// Iterate through all key-value pairs, pushing them into nodes at the right level.
|
||||||
for (key, value) in iter {
|
for (key, value) in iter {
|
||||||
// Try to push key-value pair into the current leaf node.
|
// Try to push key-value pair into the current leaf node.
|
||||||
|
@ -1126,7 +1146,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
|
|
||||||
fn fix_right_edge(&mut self) {
|
fn fix_right_edge(&mut self) {
|
||||||
// Handle underfull nodes, start from the top.
|
// Handle underfull nodes, start from the top.
|
||||||
let mut cur_node = self.root.as_mut();
|
let mut cur_node = self.root.as_mut().unwrap().as_mut();
|
||||||
while let Internal(internal) = cur_node.force() {
|
while let Internal(internal) = cur_node.force() {
|
||||||
// Check if right-most child is underfull.
|
// Check if right-most child is underfull.
|
||||||
let mut last_edge = internal.last_edge();
|
let mut last_edge = internal.last_edge();
|
||||||
|
@ -1187,14 +1207,14 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
let total_num = self.len();
|
let total_num = self.len();
|
||||||
|
|
||||||
let mut right = Self::new();
|
let mut right = Self::new();
|
||||||
right.root = node::Root::new_leaf();
|
let right_root = right.ensure_root_is_owned();
|
||||||
for _ in 0..(self.root.as_ref().height()) {
|
for _ in 0..(self.root.as_ref().unwrap().as_ref().height()) {
|
||||||
right.root.push_level();
|
right_root.push_level();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut left_node = self.root.as_mut();
|
let mut left_node = self.root.as_mut().unwrap().as_mut();
|
||||||
let mut right_node = right.root.as_mut();
|
let mut right_node = right.root.as_mut().unwrap().as_mut();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut split_edge = match search::search_node(left_node, key) {
|
let mut split_edge = match search::search_node(left_node, key) {
|
||||||
|
@ -1223,7 +1243,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
self.fix_right_border();
|
self.fix_right_border();
|
||||||
right.fix_left_border();
|
right.fix_left_border();
|
||||||
|
|
||||||
if self.root.as_ref().height() < right.root.as_ref().height() {
|
if self.root.as_ref().unwrap().as_ref().height()
|
||||||
|
< right.root.as_ref().unwrap().as_ref().height()
|
||||||
|
{
|
||||||
self.recalc_length();
|
self.recalc_length();
|
||||||
right.length = total_num - self.len();
|
right.length = total_num - self.len();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1261,19 +1283,19 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
self.length = dfs(self.root.as_ref());
|
self.length = dfs(self.root.as_ref().unwrap().as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes empty levels on the top.
|
/// Removes empty levels on the top.
|
||||||
fn fix_top(&mut self) {
|
fn fix_top(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
{
|
{
|
||||||
let node = self.root.as_ref();
|
let node = self.root.as_ref().unwrap().as_ref();
|
||||||
if node.height() == 0 || node.len() > 0 {
|
if node.height() == 0 || node.len() > 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.root.pop_level();
|
self.root.as_mut().unwrap().pop_level();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1281,7 +1303,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
self.fix_top();
|
self.fix_top();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut cur_node = self.root.as_mut();
|
let mut cur_node = self.root.as_mut().unwrap().as_mut();
|
||||||
|
|
||||||
while let Internal(node) = cur_node.force() {
|
while let Internal(node) = cur_node.force() {
|
||||||
let mut last_kv = node.last_kv();
|
let mut last_kv = node.last_kv();
|
||||||
|
@ -1307,7 +1329,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
self.fix_top();
|
self.fix_top();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut cur_node = self.root.as_mut();
|
let mut cur_node = self.root.as_mut().unwrap().as_mut();
|
||||||
|
|
||||||
while let Internal(node) = cur_node.force() {
|
while let Internal(node) = cur_node.force() {
|
||||||
let mut first_kv = node.first_kv();
|
let mut first_kv = node.first_kv();
|
||||||
|
@ -1326,13 +1348,6 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
|
|
||||||
self.fix_top();
|
self.fix_top();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the root node is the shared root node, allocate our own node.
|
|
||||||
fn ensure_root_is_owned(&mut self) {
|
|
||||||
if self.root.is_shared_root() {
|
|
||||||
self.root = node::Root::new_leaf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -1458,12 +1473,21 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
|
||||||
type IntoIter = IntoIter<K, V>;
|
type IntoIter = IntoIter<K, V>;
|
||||||
|
|
||||||
fn into_iter(self) -> IntoIter<K, V> {
|
fn into_iter(self) -> IntoIter<K, V> {
|
||||||
let root1 = unsafe { ptr::read(&self.root).into_ref() };
|
if self.root.is_none() {
|
||||||
let root2 = unsafe { ptr::read(&self.root).into_ref() };
|
mem::forget(self);
|
||||||
|
return IntoIter { front: None, back: None, length: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
let root1 = unsafe { unwrap_unchecked(ptr::read(&self.root)).into_ref() };
|
||||||
|
let root2 = unsafe { unwrap_unchecked(ptr::read(&self.root)).into_ref() };
|
||||||
let len = self.length;
|
let len = self.length;
|
||||||
mem::forget(self);
|
mem::forget(self);
|
||||||
|
|
||||||
IntoIter { front: root1.first_leaf_edge(), back: root2.last_leaf_edge(), length: len }
|
IntoIter {
|
||||||
|
front: Some(root1.first_leaf_edge()),
|
||||||
|
back: Some(root2.last_leaf_edge()),
|
||||||
|
length: len,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1478,9 +1502,9 @@ impl<K, V> Drop for IntoIter<K, V> {
|
||||||
// don't have to care about panics this time (they'll abort).
|
// don't have to care about panics this time (they'll abort).
|
||||||
while let Some(_) = self.0.next() {}
|
while let Some(_) = self.0.next() {}
|
||||||
|
|
||||||
// No need to avoid the shared root, because the tree was definitely not empty.
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut node = ptr::read(&self.0.front).into_node().forget_type();
|
let mut node =
|
||||||
|
unwrap_unchecked(ptr::read(&self.0.front)).into_node().forget_type();
|
||||||
while let Some(parent) = node.deallocate_and_ascend() {
|
while let Some(parent) = node.deallocate_and_ascend() {
|
||||||
node = parent.into_node().forget_type();
|
node = parent.into_node().forget_type();
|
||||||
}
|
}
|
||||||
|
@ -1495,14 +1519,13 @@ impl<K, V> Drop for IntoIter<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut node = ptr::read(&self.front).into_node().forget_type();
|
if let Some(front) = ptr::read(&self.front) {
|
||||||
if node.is_shared_root() {
|
let mut node = front.into_node().forget_type();
|
||||||
return;
|
// Most of the nodes have been deallocated while traversing
|
||||||
}
|
// but one pile from a leaf up to the root is left standing.
|
||||||
// Most of the nodes have been deallocated while traversing
|
while let Some(parent) = node.deallocate_and_ascend() {
|
||||||
// but one pile from a leaf up to the root is left standing.
|
node = parent.into_node().forget_type();
|
||||||
while let Some(parent) = node.deallocate_and_ascend() {
|
}
|
||||||
node = parent.into_node().forget_type();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1517,7 +1540,7 @@ impl<K, V> Iterator for IntoIter<K, V> {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
self.length -= 1;
|
self.length -= 1;
|
||||||
Some(unsafe { self.front.next_unchecked() })
|
Some(unsafe { self.front.as_mut().unwrap().next_unchecked() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1533,7 +1556,7 @@ impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
self.length -= 1;
|
self.length -= 1;
|
||||||
Some(unsafe { self.back.next_back_unchecked() })
|
Some(unsafe { self.back.as_mut().unwrap().next_back_unchecked() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1683,7 +1706,7 @@ impl<'a, K, V> Range<'a, K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
|
unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
|
||||||
self.front.next_unchecked()
|
unwrap_unchecked(self.front.as_mut()).next_unchecked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1696,7 +1719,7 @@ impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> {
|
||||||
|
|
||||||
impl<'a, K, V> Range<'a, K, V> {
|
impl<'a, K, V> Range<'a, K, V> {
|
||||||
unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
|
unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
|
||||||
self.back.next_back_unchecked()
|
unwrap_unchecked(self.back.as_mut()).next_back_unchecked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1734,7 +1757,7 @@ impl<'a, K, V> RangeMut<'a, K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
|
unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
|
||||||
self.front.next_unchecked()
|
unwrap_unchecked(self.front.as_mut()).next_unchecked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1755,7 +1778,7 @@ impl<K, V> FusedIterator for RangeMut<'_, K, V> {}
|
||||||
|
|
||||||
impl<'a, K, V> RangeMut<'a, K, V> {
|
impl<'a, K, V> RangeMut<'a, K, V> {
|
||||||
unsafe fn next_back_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
|
unsafe fn next_back_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
|
||||||
self.back.next_back_unchecked()
|
unwrap_unchecked(self.back.as_mut()).next_back_unchecked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1969,8 +1992,8 @@ impl<K, V> BTreeMap<K, V> {
|
||||||
pub fn iter(&self) -> Iter<'_, K, V> {
|
pub fn iter(&self) -> Iter<'_, K, V> {
|
||||||
Iter {
|
Iter {
|
||||||
range: Range {
|
range: Range {
|
||||||
front: self.root.as_ref().first_leaf_edge(),
|
front: self.root.as_ref().map(|r| r.as_ref().first_leaf_edge()),
|
||||||
back: self.root.as_ref().last_leaf_edge(),
|
back: self.root.as_ref().map(|r| r.as_ref().last_leaf_edge()),
|
||||||
},
|
},
|
||||||
length: self.length,
|
length: self.length,
|
||||||
}
|
}
|
||||||
|
@ -1999,13 +2022,17 @@ impl<K, V> BTreeMap<K, V> {
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
|
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
|
||||||
let root1 = self.root.as_mut();
|
|
||||||
let root2 = unsafe { ptr::read(&root1) };
|
|
||||||
IterMut {
|
IterMut {
|
||||||
range: RangeMut {
|
range: if let Some(root) = &mut self.root {
|
||||||
front: root1.first_leaf_edge(),
|
let root1 = root.as_mut();
|
||||||
back: root2.last_leaf_edge(),
|
let root2 = unsafe { ptr::read(&root1) };
|
||||||
_marker: PhantomData,
|
RangeMut {
|
||||||
|
front: Some(root1.first_leaf_edge()),
|
||||||
|
back: Some(root2.last_leaf_edge()),
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RangeMut { front: None, back: None, _marker: PhantomData }
|
||||||
},
|
},
|
||||||
length: self.length,
|
length: self.length,
|
||||||
}
|
}
|
||||||
|
@ -2116,6 +2143,12 @@ impl<K, V> BTreeMap<K, V> {
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.len() == 0
|
self.len() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the root node is the empty (non-allocated) root node, allocate our
|
||||||
|
/// own node.
|
||||||
|
fn ensure_root_is_owned(&mut self) -> &mut node::Root<K, V> {
|
||||||
|
self.root.get_or_insert_with(|| node::Root::new_leaf())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K: Ord, V> Entry<'a, K, V> {
|
impl<'a, K: Ord, V> Entry<'a, K, V> {
|
||||||
|
|
|
@ -44,34 +44,7 @@ const B: usize = 6;
|
||||||
pub const MIN_LEN: usize = B - 1;
|
pub const MIN_LEN: usize = B - 1;
|
||||||
pub const CAPACITY: usize = 2 * B - 1;
|
pub const CAPACITY: usize = 2 * B - 1;
|
||||||
|
|
||||||
/// The underlying representation of leaf nodes. Note that it is often unsafe to actually store
|
/// The underlying representation of leaf nodes.
|
||||||
/// these, since only the first `len` keys and values are assumed to be initialized. As such,
|
|
||||||
/// these should always be put behind pointers, and specifically behind `BoxedNode` in the owned
|
|
||||||
/// case.
|
|
||||||
///
|
|
||||||
/// We have a separate type for the header and rely on it matching the prefix of `LeafNode`, in
|
|
||||||
/// order to statically allocate a single dummy node to avoid allocations. This struct is
|
|
||||||
/// `repr(C)` to prevent them from being reordered. `LeafNode` does not just contain a
|
|
||||||
/// `NodeHeader` because we do not want unnecessary padding between `len` and the keys.
|
|
||||||
/// Crucially, `NodeHeader` can be safely transmuted to different K and V. (This is exploited
|
|
||||||
/// by `as_header`.)
|
|
||||||
#[repr(C)]
|
|
||||||
struct NodeHeader<K, V> {
|
|
||||||
/// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
|
|
||||||
/// This either points to an actual node or is null.
|
|
||||||
parent: *const InternalNode<K, V>,
|
|
||||||
|
|
||||||
/// This node's index into the parent node's `edges` array.
|
|
||||||
/// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`.
|
|
||||||
/// This is only guaranteed to be initialized when `parent` is non-null.
|
|
||||||
parent_idx: MaybeUninit<u16>,
|
|
||||||
|
|
||||||
/// The number of keys and values this node stores.
|
|
||||||
///
|
|
||||||
/// This next to `parent_idx` to encourage the compiler to join `len` and
|
|
||||||
/// `parent_idx` into the same 32-bit word, reducing space overhead.
|
|
||||||
len: u16,
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct LeafNode<K, V> {
|
struct LeafNode<K, V> {
|
||||||
/// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
|
/// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
|
||||||
|
@ -111,21 +84,6 @@ impl<K, V> LeafNode<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K, V> NodeHeader<K, V> {
|
|
||||||
fn is_shared_root(&self) -> bool {
|
|
||||||
ptr::eq(self, &EMPTY_ROOT_NODE as *const _ as *const _)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to implement Sync here in order to make a static instance.
|
|
||||||
unsafe impl Sync for NodeHeader<(), ()> {}
|
|
||||||
|
|
||||||
// An empty node used as a placeholder for the root node, to avoid allocations.
|
|
||||||
// We use just a header in order to save space, since no operation on an empty tree will
|
|
||||||
// ever take a pointer past the first key.
|
|
||||||
static EMPTY_ROOT_NODE: NodeHeader<(), ()> =
|
|
||||||
NodeHeader { parent: ptr::null(), parent_idx: MaybeUninit::uninit(), len: 0 };
|
|
||||||
|
|
||||||
/// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
|
/// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
|
||||||
/// behind `BoxedNode`s to prevent dropping uninitialized keys and values. Any pointer to an
|
/// behind `BoxedNode`s to prevent dropping uninitialized keys and values. Any pointer to an
|
||||||
/// `InternalNode` can be directly casted to a pointer to the underlying `LeafNode` portion of the
|
/// `InternalNode` can be directly casted to a pointer to the underlying `LeafNode` portion of the
|
||||||
|
@ -154,12 +112,9 @@ impl<K, V> InternalNode<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A managed, non-null pointer to a node. This is either an owned pointer to
|
/// A managed, non-null pointer to a node. This is either an owned pointer to
|
||||||
/// `LeafNode<K, V>`, an owned pointer to `InternalNode<K, V>`, or a (not owned)
|
/// `LeafNode<K, V>` or an owned pointer to `InternalNode<K, V>`.
|
||||||
/// pointer to `NodeHeader<(), ()` (more specifically, the pointer to EMPTY_ROOT_NODE).
|
///
|
||||||
/// All of these types have a `NodeHeader<K, V>` prefix, meaning that they have at
|
/// However, `BoxedNode` contains no information as to which of the two types
|
||||||
/// least the same size as `NodeHeader<K, V>` and store the same kinds of data at the same
|
|
||||||
/// offsets; and they have a pointer alignment at least as large as `NodeHeader<K, V>`'s.
|
|
||||||
/// However, `BoxedNode` contains no information as to which of the three types
|
|
||||||
/// of nodes it actually contains, and, partially due to this lack of information,
|
/// of nodes it actually contains, and, partially due to this lack of information,
|
||||||
/// has no destructor.
|
/// has no destructor.
|
||||||
struct BoxedNode<K, V> {
|
struct BoxedNode<K, V> {
|
||||||
|
@ -184,8 +139,9 @@ impl<K, V> BoxedNode<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Either an owned tree or a shared, empty tree. Note that this does not have a destructor,
|
/// An owned tree.
|
||||||
/// and must be cleaned up manually if it is an owned tree.
|
///
|
||||||
|
/// Note that this does not have a destructor, and must be cleaned up manually.
|
||||||
pub struct Root<K, V> {
|
pub struct Root<K, V> {
|
||||||
node: BoxedNode<K, V>,
|
node: BoxedNode<K, V>,
|
||||||
/// The number of levels below the root node.
|
/// The number of levels below the root node.
|
||||||
|
@ -196,20 +152,6 @@ unsafe impl<K: Sync, V: Sync> Sync for Root<K, V> {}
|
||||||
unsafe impl<K: Send, V: Send> Send for Root<K, V> {}
|
unsafe impl<K: Send, V: Send> Send for Root<K, V> {}
|
||||||
|
|
||||||
impl<K, V> Root<K, V> {
|
impl<K, V> Root<K, V> {
|
||||||
/// Whether the instance of `Root` wraps a shared, empty root node. If not,
|
|
||||||
/// the entire tree is uniquely owned by the owner of the `Root` instance.
|
|
||||||
pub fn is_shared_root(&self) -> bool {
|
|
||||||
self.as_ref().is_shared_root()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a shared tree, wrapping a shared root node that is eternally empty.
|
|
||||||
pub fn shared_empty_root() -> Self {
|
|
||||||
Root {
|
|
||||||
node: unsafe { BoxedNode::from_ptr(NonNull::from(&EMPTY_ROOT_NODE).cast()) },
|
|
||||||
height: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new owned tree, with its own root node that is initially empty.
|
/// Returns a new owned tree, with its own root node that is initially empty.
|
||||||
pub fn new_leaf() -> Self {
|
pub fn new_leaf() -> Self {
|
||||||
Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }
|
Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }
|
||||||
|
@ -245,7 +187,6 @@ impl<K, V> Root<K, V> {
|
||||||
/// Adds a new internal node with a single edge, pointing to the previous root, and make that
|
/// Adds a new internal node with a single edge, pointing to the previous root, and make that
|
||||||
/// new node the root. This increases the height by 1 and is the opposite of `pop_level`.
|
/// new node the root. This increases the height by 1 and is the opposite of `pop_level`.
|
||||||
pub fn push_level(&mut self) -> NodeRef<marker::Mut<'_>, K, V, marker::Internal> {
|
pub fn push_level(&mut self) -> NodeRef<marker::Mut<'_>, K, V, marker::Internal> {
|
||||||
debug_assert!(!self.is_shared_root());
|
|
||||||
let mut new_node = Box::new(unsafe { InternalNode::new() });
|
let mut new_node = Box::new(unsafe { InternalNode::new() });
|
||||||
new_node.edges[0].write(unsafe { BoxedNode::from_ptr(self.node.as_ptr()) });
|
new_node.edges[0].write(unsafe { BoxedNode::from_ptr(self.node.as_ptr()) });
|
||||||
|
|
||||||
|
@ -308,11 +249,6 @@ impl<K, V> Root<K, V> {
|
||||||
/// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the
|
/// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the
|
||||||
/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
|
/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
|
||||||
/// `NodeRef` could be pointing to either type of node.
|
/// `NodeRef` could be pointing to either type of node.
|
||||||
/// Note that in case of a leaf node, this might still be the shared root!
|
|
||||||
/// Only turn this into a `LeafNode` reference if you know it is not the shared root!
|
|
||||||
/// Shared references must be dereferenceable *for the entire size of their pointee*,
|
|
||||||
/// so '&LeafNode` or `&InternalNode` pointing to the shared root is undefined behavior.
|
|
||||||
/// Turning this into a `NodeHeader` reference is always safe.
|
|
||||||
pub struct NodeRef<BorrowType, K, V, Type> {
|
pub struct NodeRef<BorrowType, K, V, Type> {
|
||||||
/// The number of levels below the node.
|
/// The number of levels below the node.
|
||||||
height: usize,
|
height: usize,
|
||||||
|
@ -354,7 +290,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||||
/// Note that, despite being safe, calling this function can have the side effect
|
/// Note that, despite being safe, calling this function can have the side effect
|
||||||
/// of invalidating mutable references that unsafe code has created.
|
/// of invalidating mutable references that unsafe code has created.
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.as_header().len as usize
|
self.as_leaf().len as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the height of this node in the whole tree. Zero height denotes the
|
/// Returns the height of this node in the whole tree. Zero height denotes the
|
||||||
|
@ -374,35 +310,24 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||||
NodeRef { height: self.height, node: self.node, root: self.root, _marker: PhantomData }
|
NodeRef { height: self.height, node: self.node, root: self.root, _marker: PhantomData }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Exposes the leaf "portion" of any leaf or internal node that is not the shared root.
|
/// Exposes the leaf "portion" of any leaf or internal node.
|
||||||
/// If the node is a leaf, this function simply opens up its data.
|
/// If the node is a leaf, this function simply opens up its data.
|
||||||
/// If the node is an internal node, so not a leaf, it does have all the data a leaf has
|
/// If the node is an internal node, so not a leaf, it does have all the data a leaf has
|
||||||
/// (header, keys and values), and this function exposes that.
|
/// (header, keys and values), and this function exposes that.
|
||||||
/// Unsafe because the node must not be the shared root. For more information,
|
fn as_leaf(&self) -> &LeafNode<K, V> {
|
||||||
/// see the `NodeRef` comments.
|
// The node must be valid for at least the LeafNode portion.
|
||||||
unsafe fn as_leaf(&self) -> &LeafNode<K, V> {
|
// This is not a reference in the NodeRef type because we don't know if
|
||||||
debug_assert!(!self.is_shared_root());
|
// it should be unique or shared.
|
||||||
self.node.as_ref()
|
unsafe { self.node.as_ref() }
|
||||||
}
|
|
||||||
|
|
||||||
fn as_header(&self) -> &NodeHeader<K, V> {
|
|
||||||
unsafe { &*(self.node.as_ptr() as *const NodeHeader<K, V>) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns whether the node is the shared, empty root.
|
|
||||||
pub fn is_shared_root(&self) -> bool {
|
|
||||||
self.as_header().is_shared_root()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrows a view into the keys stored in the node.
|
/// Borrows a view into the keys stored in the node.
|
||||||
/// Unsafe because the caller must ensure that the node is not the shared root.
|
pub fn keys(&self) -> &[K] {
|
||||||
pub unsafe fn keys(&self) -> &[K] {
|
|
||||||
self.reborrow().into_key_slice()
|
self.reborrow().into_key_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrows a view into the values stored in the node.
|
/// Borrows a view into the values stored in the node.
|
||||||
/// Unsafe because the caller must ensure that the node is not the shared root.
|
fn vals(&self) -> &[V] {
|
||||||
unsafe fn vals(&self) -> &[V] {
|
|
||||||
self.reborrow().into_val_slice()
|
self.reborrow().into_val_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,7 +341,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||||
pub fn ascend(
|
pub fn ascend(
|
||||||
self,
|
self,
|
||||||
) -> Result<Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>, Self> {
|
) -> Result<Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>, Self> {
|
||||||
let parent_as_leaf = self.as_header().parent as *const LeafNode<K, V>;
|
let parent_as_leaf = self.as_leaf().parent as *const LeafNode<K, V>;
|
||||||
if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) {
|
if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) {
|
||||||
Ok(Handle {
|
Ok(Handle {
|
||||||
node: NodeRef {
|
node: NodeRef {
|
||||||
|
@ -425,7 +350,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||||
root: self.root,
|
root: self.root,
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
},
|
},
|
||||||
idx: unsafe { usize::from(*self.as_header().parent_idx.as_ptr()) },
|
idx: unsafe { usize::from(*self.as_leaf().parent_idx.as_ptr()) },
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -464,7 +389,6 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
|
||||||
pub unsafe fn deallocate_and_ascend(
|
pub unsafe fn deallocate_and_ascend(
|
||||||
self,
|
self,
|
||||||
) -> Option<Handle<NodeRef<marker::Owned, K, V, marker::Internal>, marker::Edge>> {
|
) -> Option<Handle<NodeRef<marker::Owned, K, V, marker::Internal>, marker::Edge>> {
|
||||||
assert!(!self.is_shared_root());
|
|
||||||
let height = self.height;
|
let height = self.height;
|
||||||
let node = self.node;
|
let node = self.node;
|
||||||
let ret = self.ascend().ok();
|
let ret = self.ascend().ok();
|
||||||
|
@ -507,41 +431,37 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
|
||||||
/// (header, keys and values), and this function exposes that.
|
/// (header, keys and values), and this function exposes that.
|
||||||
///
|
///
|
||||||
/// Returns a raw ptr to avoid asserting exclusive access to the entire node.
|
/// Returns a raw ptr to avoid asserting exclusive access to the entire node.
|
||||||
/// This also implies you can invoke this member on the shared root, but the resulting pointer
|
|
||||||
/// might not be properly aligned and definitely would not allow accessing keys and values.
|
|
||||||
fn as_leaf_mut(&mut self) -> *mut LeafNode<K, V> {
|
fn as_leaf_mut(&mut self) -> *mut LeafNode<K, V> {
|
||||||
self.node.as_ptr()
|
self.node.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsafe because the caller must ensure that the node is not the shared root.
|
fn keys_mut(&mut self) -> &mut [K] {
|
||||||
unsafe fn keys_mut(&mut self) -> &mut [K] {
|
// SAFETY: the caller will not be able to call further methods on self
|
||||||
self.reborrow_mut().into_key_slice_mut()
|
// until the key slice reference is dropped, as we have unique access
|
||||||
|
// for the lifetime of the borrow.
|
||||||
|
unsafe { self.reborrow_mut().into_key_slice_mut() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsafe because the caller must ensure that the node is not the shared root.
|
fn vals_mut(&mut self) -> &mut [V] {
|
||||||
unsafe fn vals_mut(&mut self) -> &mut [V] {
|
// SAFETY: the caller will not be able to call further methods on self
|
||||||
self.reborrow_mut().into_val_slice_mut()
|
// until the value slice reference is dropped, as we have unique access
|
||||||
|
// for the lifetime of the borrow.
|
||||||
|
unsafe { self.reborrow_mut().into_val_slice_mut() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
|
impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
|
||||||
/// Unsafe because the caller must ensure that the node is not the shared root.
|
fn into_key_slice(self) -> &'a [K] {
|
||||||
unsafe fn into_key_slice(self) -> &'a [K] {
|
unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len()) }
|
||||||
debug_assert!(!self.is_shared_root());
|
|
||||||
// We cannot be the shared root, so `as_leaf` is okay.
|
|
||||||
slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsafe because the caller must ensure that the node is not the shared root.
|
fn into_val_slice(self) -> &'a [V] {
|
||||||
unsafe fn into_val_slice(self) -> &'a [V] {
|
unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len()) }
|
||||||
debug_assert!(!self.is_shared_root());
|
|
||||||
// We cannot be the shared root, so `as_leaf` is okay.
|
|
||||||
slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsafe because the caller must ensure that the node is not the shared root.
|
fn into_slices(self) -> (&'a [K], &'a [V]) {
|
||||||
unsafe fn into_slices(self) -> (&'a [K], &'a [V]) {
|
// SAFETY: equivalent to reborrow() except not requiring Type: 'a
|
||||||
let k = ptr::read(&self);
|
let k = unsafe { ptr::read(&self) };
|
||||||
(k.into_key_slice(), self.into_val_slice())
|
(k.into_key_slice(), self.into_val_slice())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,28 +473,27 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
|
||||||
unsafe { &mut *(self.root as *mut Root<K, V>) }
|
unsafe { &mut *(self.root as *mut Root<K, V>) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsafe because the caller must ensure that the node is not the shared root.
|
fn into_key_slice_mut(mut self) -> &'a mut [K] {
|
||||||
unsafe fn into_key_slice_mut(mut self) -> &'a mut [K] {
|
// SAFETY: The keys of a node must always be initialized up to length.
|
||||||
debug_assert!(!self.is_shared_root());
|
unsafe {
|
||||||
// We cannot be the shared root, so `as_leaf_mut` is okay.
|
slice::from_raw_parts_mut(
|
||||||
slice::from_raw_parts_mut(
|
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys),
|
||||||
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys),
|
self.len(),
|
||||||
self.len(),
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsafe because the caller must ensure that the node is not the shared root.
|
fn into_val_slice_mut(mut self) -> &'a mut [V] {
|
||||||
unsafe fn into_val_slice_mut(mut self) -> &'a mut [V] {
|
// SAFETY: The values of a node must always be initialized up to length.
|
||||||
debug_assert!(!self.is_shared_root());
|
unsafe {
|
||||||
slice::from_raw_parts_mut(
|
slice::from_raw_parts_mut(
|
||||||
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).vals),
|
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).vals),
|
||||||
self.len(),
|
self.len(),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsafe because the caller must ensure that the node is not the shared root.
|
fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) {
|
||||||
unsafe fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) {
|
|
||||||
debug_assert!(!self.is_shared_root());
|
|
||||||
// We cannot use the getters here, because calling the second one
|
// We cannot use the getters here, because calling the second one
|
||||||
// invalidates the reference returned by the first.
|
// invalidates the reference returned by the first.
|
||||||
// More precisely, it is the call to `len` that is the culprit,
|
// More precisely, it is the call to `len` that is the culprit,
|
||||||
|
@ -582,8 +501,13 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
|
||||||
// overlap with the keys (and even the values, for ZST keys).
|
// overlap with the keys (and even the values, for ZST keys).
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
let leaf = self.as_leaf_mut();
|
let leaf = self.as_leaf_mut();
|
||||||
let keys = slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).keys), len);
|
// SAFETY: The keys and values of a node must always be initialized up to length.
|
||||||
let vals = slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len);
|
let keys = unsafe {
|
||||||
|
slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).keys), len)
|
||||||
|
};
|
||||||
|
let vals = unsafe {
|
||||||
|
slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len)
|
||||||
|
};
|
||||||
(keys, vals)
|
(keys, vals)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -592,7 +516,6 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
|
||||||
/// Adds a key/value pair the end of the node.
|
/// Adds a key/value pair the end of the node.
|
||||||
pub fn push(&mut self, key: K, val: V) {
|
pub fn push(&mut self, key: K, val: V) {
|
||||||
assert!(self.len() < CAPACITY);
|
assert!(self.len() < CAPACITY);
|
||||||
debug_assert!(!self.is_shared_root());
|
|
||||||
|
|
||||||
let idx = self.len();
|
let idx = self.len();
|
||||||
|
|
||||||
|
@ -607,7 +530,6 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
|
||||||
/// Adds a key/value pair to the beginning of the node.
|
/// Adds a key/value pair to the beginning of the node.
|
||||||
pub fn push_front(&mut self, key: K, val: V) {
|
pub fn push_front(&mut self, key: K, val: V) {
|
||||||
assert!(self.len() < CAPACITY);
|
assert!(self.len() < CAPACITY);
|
||||||
debug_assert!(!self.is_shared_root());
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
slice_insert(self.keys_mut(), 0, key);
|
slice_insert(self.keys_mut(), 0, key);
|
||||||
|
@ -624,7 +546,6 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
||||||
pub fn push(&mut self, key: K, val: V, edge: Root<K, V>) {
|
pub fn push(&mut self, key: K, val: V, edge: Root<K, V>) {
|
||||||
assert!(edge.height == self.height - 1);
|
assert!(edge.height == self.height - 1);
|
||||||
assert!(self.len() < CAPACITY);
|
assert!(self.len() < CAPACITY);
|
||||||
debug_assert!(!self.is_shared_root());
|
|
||||||
|
|
||||||
let idx = self.len();
|
let idx = self.len();
|
||||||
|
|
||||||
|
@ -658,7 +579,6 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
||||||
pub fn push_front(&mut self, key: K, val: V, edge: Root<K, V>) {
|
pub fn push_front(&mut self, key: K, val: V, edge: Root<K, V>) {
|
||||||
assert!(edge.height == self.height - 1);
|
assert!(edge.height == self.height - 1);
|
||||||
assert!(self.len() < CAPACITY);
|
assert!(self.len() < CAPACITY);
|
||||||
debug_assert!(!self.is_shared_root());
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
slice_insert(self.keys_mut(), 0, key);
|
slice_insert(self.keys_mut(), 0, key);
|
||||||
|
@ -744,8 +664,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsafe because the caller must ensure that the node is not the shared root.
|
fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) {
|
||||||
unsafe fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) {
|
|
||||||
(self.keys_mut().as_mut_ptr(), self.vals_mut().as_mut_ptr())
|
(self.keys_mut().as_mut_ptr(), self.vals_mut().as_mut_ptr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -904,7 +823,6 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge
|
||||||
fn insert_fit(&mut self, key: K, val: V) -> *mut V {
|
fn insert_fit(&mut self, key: K, val: V) -> *mut V {
|
||||||
// Necessary for correctness, but in a private module
|
// Necessary for correctness, but in a private module
|
||||||
debug_assert!(self.node.len() < CAPACITY);
|
debug_assert!(self.node.len() < CAPACITY);
|
||||||
debug_assert!(!self.node.is_shared_root());
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
slice_insert(self.node.keys_mut(), self.idx, key);
|
slice_insert(self.node.keys_mut(), self.idx, key);
|
||||||
|
@ -1081,7 +999,6 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
|
||||||
/// - All the key/value pairs to the right of this handle are put into a newly
|
/// - All the key/value pairs to the right of this handle are put into a newly
|
||||||
/// allocated node.
|
/// allocated node.
|
||||||
pub fn split(mut self) -> (NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, K, V, Root<K, V>) {
|
pub fn split(mut self) -> (NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, K, V, Root<K, V>) {
|
||||||
assert!(!self.node.is_shared_root());
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut new_node = Box::new(LeafNode::new());
|
let mut new_node = Box::new(LeafNode::new());
|
||||||
|
|
||||||
|
@ -1113,7 +1030,6 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
|
||||||
pub fn remove(
|
pub fn remove(
|
||||||
mut self,
|
mut self,
|
||||||
) -> (Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>, K, V) {
|
) -> (Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>, K, V) {
|
||||||
assert!(!self.node.is_shared_root());
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let k = slice_remove(self.node.keys_mut(), self.idx);
|
let k = slice_remove(self.node.keys_mut(), self.idx);
|
||||||
let v = slice_remove(self.node.vals_mut(), self.idx);
|
let v = slice_remove(self.node.vals_mut(), self.idx);
|
||||||
|
|
|
@ -67,19 +67,16 @@ where
|
||||||
Q: Ord,
|
Q: Ord,
|
||||||
K: Borrow<Q>,
|
K: Borrow<Q>,
|
||||||
{
|
{
|
||||||
// This function is defined over all borrow types (immutable, mutable, owned),
|
// This function is defined over all borrow types (immutable, mutable, owned).
|
||||||
// and may be called on the shared root in each case.
|
|
||||||
// Using `keys()` is fine here even if BorrowType is mutable, as all we return
|
// Using `keys()` is fine here even if BorrowType is mutable, as all we return
|
||||||
// is an index -- not a reference.
|
// is an index -- not a reference.
|
||||||
let len = node.len();
|
let len = node.len();
|
||||||
if len > 0 {
|
let keys = node.keys();
|
||||||
let keys = unsafe { node.keys() }; // safe because a non-empty node cannot be the shared root
|
for (i, k) in keys.iter().enumerate() {
|
||||||
for (i, k) in keys.iter().enumerate() {
|
match key.cmp(k.borrow()) {
|
||||||
match key.cmp(k.borrow()) {
|
Ordering::Greater => {}
|
||||||
Ordering::Greater => {}
|
Ordering::Equal => return (i, true),
|
||||||
Ordering::Equal => return (i, true),
|
Ordering::Less => return (i, false),
|
||||||
Ordering::Less => return (i, false),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(len, false)
|
(len, false)
|
||||||
|
|
|
@ -67,7 +67,7 @@ fn test_basic_large() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_small() {
|
fn test_basic_small() {
|
||||||
let mut map = BTreeMap::new();
|
let mut map = BTreeMap::new();
|
||||||
// Empty, shared root:
|
// Empty, root is absent (None):
|
||||||
assert_eq!(map.remove(&1), None);
|
assert_eq!(map.remove(&1), None);
|
||||||
assert_eq!(map.len(), 0);
|
assert_eq!(map.len(), 0);
|
||||||
assert_eq!(map.get(&1), None);
|
assert_eq!(map.get(&1), None);
|
||||||
|
@ -123,7 +123,7 @@ fn test_basic_small() {
|
||||||
assert_eq!(map.values().collect::<Vec<_>>(), vec![&4]);
|
assert_eq!(map.values().collect::<Vec<_>>(), vec![&4]);
|
||||||
assert_eq!(map.remove(&2), Some(4));
|
assert_eq!(map.remove(&2), Some(4));
|
||||||
|
|
||||||
// Empty but private root:
|
// Empty but root is owned (Some(...)):
|
||||||
assert_eq!(map.len(), 0);
|
assert_eq!(map.len(), 0);
|
||||||
assert_eq!(map.get(&1), None);
|
assert_eq!(map.get(&1), None);
|
||||||
assert_eq!(map.get_mut(&1), None);
|
assert_eq!(map.get_mut(&1), None);
|
||||||
|
@ -263,13 +263,6 @@ fn test_iter_mut_mutation() {
|
||||||
do_test_iter_mut_mutation::<Align32>(144);
|
do_test_iter_mut_mutation::<Align32>(144);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_into_key_slice_with_shared_root_past_bounds() {
|
|
||||||
let mut map: BTreeMap<Align32, ()> = BTreeMap::new();
|
|
||||||
assert_eq!(map.get(&Align32(1)), None);
|
|
||||||
assert_eq!(map.get_mut(&Align32(1)), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_values_mut() {
|
fn test_values_mut() {
|
||||||
let mut a = BTreeMap::new();
|
let mut a = BTreeMap::new();
|
||||||
|
|
|
@ -17,35 +17,43 @@
|
||||||
// gdb-command: print btree_set
|
// gdb-command: print btree_set
|
||||||
// gdb-check:$1 = BTreeSet<i32>(len: 15) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
|
// gdb-check:$1 = BTreeSet<i32>(len: 15) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
|
||||||
|
|
||||||
|
// gdb-command: print empty_btree_set
|
||||||
|
// gdb-check:$2 = BTreeSet<i32>(len: 0)
|
||||||
|
|
||||||
// gdb-command: print btree_map
|
// gdb-command: print btree_map
|
||||||
// gdb-check:$2 = BTreeMap<i32, i32>(len: 15) = {[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, [8] = 8, [9] = 9, [10] = 10, [11] = 11, [12] = 12, [13] = 13, [14] = 14}
|
// gdb-check:$3 = BTreeMap<i32, i32>(len: 15) = {[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, [8] = 8, [9] = 9, [10] = 10, [11] = 11, [12] = 12, [13] = 13, [14] = 14}
|
||||||
|
|
||||||
|
// gdb-command: print empty_btree_map
|
||||||
|
// gdb-check:$4 = BTreeMap<i32, u32>(len: 0)
|
||||||
|
|
||||||
// gdb-command: print vec_deque
|
// gdb-command: print vec_deque
|
||||||
// gdb-check:$3 = VecDeque<i32>(len: 3, cap: 8) = {5, 3, 7}
|
// gdb-check:$5 = VecDeque<i32>(len: 3, cap: 8) = {5, 3, 7}
|
||||||
|
|
||||||
// gdb-command: print vec_deque2
|
// gdb-command: print vec_deque2
|
||||||
// gdb-check:$4 = VecDeque<i32>(len: 7, cap: 8) = {2, 3, 4, 5, 6, 7, 8}
|
// gdb-check:$6 = VecDeque<i32>(len: 7, cap: 8) = {2, 3, 4, 5, 6, 7, 8}
|
||||||
|
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
use std::collections::BTreeSet;
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
use std::collections::BTreeSet;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
||||||
// BTreeSet
|
// BTreeSet
|
||||||
let mut btree_set = BTreeSet::new();
|
let mut btree_set = BTreeSet::new();
|
||||||
for i in 0..15 {
|
for i in 0..15 {
|
||||||
btree_set.insert(i);
|
btree_set.insert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut empty_btree_set: BTreeSet<i32> = BTreeSet::new();
|
||||||
|
|
||||||
// BTreeMap
|
// BTreeMap
|
||||||
let mut btree_map = BTreeMap::new();
|
let mut btree_map = BTreeMap::new();
|
||||||
for i in 0..15 {
|
for i in 0..15 {
|
||||||
btree_map.insert(i, i);
|
btree_map.insert(i, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut empty_btree_map: BTreeMap<i32, u32> = BTreeMap::new();
|
||||||
|
|
||||||
// VecDeque
|
// VecDeque
|
||||||
let mut vec_deque = VecDeque::new();
|
let mut vec_deque = VecDeque::new();
|
||||||
vec_deque.push_back(5);
|
vec_deque.push_back(5);
|
||||||
|
@ -63,4 +71,6 @@ fn main() {
|
||||||
zzz(); // #break
|
zzz(); // #break
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zzz() { () }
|
fn zzz() {
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue