BTreeMap: move generic functions out of navigate.rs

This commit is contained in:
Stein Somers 2020-10-25 16:10:10 +01:00
parent 1cd97cad6e
commit 0da7941e1c
3 changed files with 42 additions and 40 deletions

View File

@ -0,0 +1,34 @@
use core::intrinsics;
use core::mem;
use core::ptr;
/// This replaces the value behind the `v` unique reference by calling the
/// relevant function.
///
/// If a panic occurs in the `change` closure, the entire process will be aborted.
#[inline]
pub fn take_mut<T>(v: &mut T, change: impl FnOnce(T) -> T) {
replace(v, |value| (change(value), ()))
}
/// This replaces the value behind the `v` unique reference by calling the
/// relevant function, and returns a result obtained along the way.
///
/// If a panic occurs in the `change` closure, the entire process will be aborted.
#[inline]
pub fn replace<T, R>(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R {
struct PanicGuard;
impl Drop for PanicGuard {
fn drop(&mut self) {
intrinsics::abort()
}
}
let guard = PanicGuard;
let value = unsafe { ptr::read(v) };
let (new_value, ret) = change(value);
unsafe {
ptr::write(v, new_value);
}
mem::forget(guard);
ret
}

View File

@ -1,5 +1,6 @@
mod borrow; mod borrow;
pub mod map; pub mod map;
mod mem;
mod merge_iter; mod merge_iter;
mod navigate; mod navigate;
mod node; mod node;

View File

@ -1,7 +1,5 @@
use core::borrow::Borrow; use core::borrow::Borrow;
use core::cmp::Ordering; use core::cmp::Ordering;
use core::intrinsics;
use core::mem;
use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::Bound::{Excluded, Included, Unbounded};
use core::ops::RangeBounds; use core::ops::RangeBounds;
use core::ptr; use core::ptr;
@ -304,37 +302,6 @@ macro_rules! def_next_kv_uncheched_dealloc {
def_next_kv_uncheched_dealloc! {unsafe fn next_kv_unchecked_dealloc: right_kv} def_next_kv_uncheched_dealloc! {unsafe fn next_kv_unchecked_dealloc: right_kv}
def_next_kv_uncheched_dealloc! {unsafe fn next_back_kv_unchecked_dealloc: left_kv} def_next_kv_uncheched_dealloc! {unsafe fn next_back_kv_unchecked_dealloc: left_kv}
/// This replaces the value behind the `v` unique reference by calling the
/// relevant function.
///
/// If a panic occurs in the `change` closure, the entire process will be aborted.
#[inline]
fn take_mut<T>(v: &mut T, change: impl FnOnce(T) -> T) {
replace(v, |value| (change(value), ()))
}
/// This replaces the value behind the `v` unique reference by calling the
/// relevant function, and returns a result obtained along the way.
///
/// If a panic occurs in the `change` closure, the entire process will be aborted.
#[inline]
fn replace<T, R>(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R {
struct PanicGuard;
impl Drop for PanicGuard {
fn drop(&mut self) {
intrinsics::abort()
}
}
let guard = PanicGuard;
let value = unsafe { ptr::read(v) };
let (new_value, ret) = change(value);
unsafe {
ptr::write(v, new_value);
}
mem::forget(guard);
ret
}
impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge> { impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge> {
/// Moves the leaf edge handle to the next leaf edge and returns references to the /// Moves the leaf edge handle to the next leaf edge and returns references to the
/// key and value in between. /// key and value in between.
@ -342,7 +309,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Ed
/// # Safety /// # Safety
/// There must be another KV in the direction travelled. /// There must be another KV in the direction travelled.
pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
replace(self, |leaf_edge| { super::mem::replace(self, |leaf_edge| {
let kv = leaf_edge.next_kv(); let kv = leaf_edge.next_kv();
let kv = unsafe { unwrap_unchecked(kv.ok()) }; let kv = unsafe { unwrap_unchecked(kv.ok()) };
(kv.next_leaf_edge(), kv.into_kv()) (kv.next_leaf_edge(), kv.into_kv())
@ -355,7 +322,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Ed
/// # Safety /// # Safety
/// There must be another KV in the direction travelled. /// There must be another KV in the direction travelled.
pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
replace(self, |leaf_edge| { super::mem::replace(self, |leaf_edge| {
let kv = leaf_edge.next_back_kv(); let kv = leaf_edge.next_back_kv();
let kv = unsafe { unwrap_unchecked(kv.ok()) }; let kv = unsafe { unwrap_unchecked(kv.ok()) };
(kv.next_back_leaf_edge(), kv.into_kv()) (kv.next_back_leaf_edge(), kv.into_kv())
@ -370,7 +337,7 @@ impl<'a, K, V> Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::E
/// # Safety /// # Safety
/// There must be another KV in the direction travelled. /// There must be another KV in the direction travelled.
pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
let kv = replace(self, |leaf_edge| { let kv = super::mem::replace(self, |leaf_edge| {
let kv = leaf_edge.next_kv(); let kv = leaf_edge.next_kv();
let kv = unsafe { unwrap_unchecked(kv.ok()) }; let kv = unsafe { unwrap_unchecked(kv.ok()) };
(unsafe { ptr::read(&kv) }.next_leaf_edge(), kv) (unsafe { ptr::read(&kv) }.next_leaf_edge(), kv)
@ -385,7 +352,7 @@ impl<'a, K, V> Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::E
/// # Safety /// # Safety
/// There must be another KV in the direction travelled. /// There must be another KV in the direction travelled.
pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
let kv = replace(self, |leaf_edge| { let kv = super::mem::replace(self, |leaf_edge| {
let kv = leaf_edge.next_back_kv(); let kv = leaf_edge.next_back_kv();
let kv = unsafe { unwrap_unchecked(kv.ok()) }; let kv = unsafe { unwrap_unchecked(kv.ok()) };
(unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv) (unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv)
@ -401,7 +368,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge
/// # Safety /// # Safety
/// There must be another KV in the direction travelled. /// There must be another KV in the direction travelled.
pub unsafe fn move_next_unchecked(&mut self) { pub unsafe fn move_next_unchecked(&mut self) {
take_mut(self, |leaf_edge| { super::mem::take_mut(self, |leaf_edge| {
let kv = leaf_edge.next_kv(); let kv = leaf_edge.next_kv();
let kv = unsafe { unwrap_unchecked(kv.ok()) }; let kv = unsafe { unwrap_unchecked(kv.ok()) };
kv.next_leaf_edge() kv.next_leaf_edge()
@ -423,7 +390,7 @@ impl<K, V> Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge> {
/// call this method again subject to its safety conditions, or call counterpart /// call this method again subject to its safety conditions, or call counterpart
/// `next_back_unchecked` subject to its safety conditions. /// `next_back_unchecked` subject to its safety conditions.
pub unsafe fn next_unchecked(&mut self) -> (K, V) { pub unsafe fn next_unchecked(&mut self) -> (K, V) {
replace(self, |leaf_edge| { super::mem::replace(self, |leaf_edge| {
let kv = unsafe { next_kv_unchecked_dealloc(leaf_edge) }; let kv = unsafe { next_kv_unchecked_dealloc(leaf_edge) };
let k = unsafe { ptr::read(kv.reborrow().into_kv().0) }; let k = unsafe { ptr::read(kv.reborrow().into_kv().0) };
let v = unsafe { ptr::read(kv.reborrow().into_kv().1) }; let v = unsafe { ptr::read(kv.reborrow().into_kv().1) };
@ -444,7 +411,7 @@ impl<K, V> Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge> {
/// call this method again subject to its safety conditions, or call counterpart /// call this method again subject to its safety conditions, or call counterpart
/// `next_unchecked` subject to its safety conditions. /// `next_unchecked` subject to its safety conditions.
pub unsafe fn next_back_unchecked(&mut self) -> (K, V) { pub unsafe fn next_back_unchecked(&mut self) -> (K, V) {
replace(self, |leaf_edge| { super::mem::replace(self, |leaf_edge| {
let kv = unsafe { next_back_kv_unchecked_dealloc(leaf_edge) }; let kv = unsafe { next_back_kv_unchecked_dealloc(leaf_edge) };
let k = unsafe { ptr::read(kv.reborrow().into_kv().0) }; let k = unsafe { ptr::read(kv.reborrow().into_kv().0) };
let v = unsafe { ptr::read(kv.reborrow().into_kv().1) }; let v = unsafe { ptr::read(kv.reborrow().into_kv().1) };