Rollup merge of #75519 - ssomers:btree_splitpoint_cleanup, r=Mark-Simulacrum

BTreeMap: refactor splitpoint and move testing over to unit test

r? @Mark-Simulacrum
This commit is contained in:
Tyler Mandry 2020-08-14 14:47:01 -07:00 committed by GitHub
commit 2564135115
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 31 deletions

View file

@ -43,6 +43,9 @@ use crate::boxed::Box;
const B: usize = 6;
pub const MIN_LEN: usize = B - 1;
pub const CAPACITY: usize = 2 * B - 1;
const KV_IDX_CENTER: usize = B - 1;
const EDGE_IDX_LEFT_OF_CENTER: usize = B - 1;
const EDGE_IDX_RIGHT_OF_CENTER: usize = B;
/// The underlying representation of leaf nodes.
#[repr(C)]
@ -834,38 +837,12 @@ enum InsertionPlace {
fn splitpoint(edge_idx: usize) -> (usize, InsertionPlace) {
debug_assert!(edge_idx <= CAPACITY);
// Rust issue #74834 tries to explain these symmetric rules.
let middle_kv_idx;
let insertion;
if edge_idx <= B - 2 {
middle_kv_idx = B - 2;
insertion = InsertionPlace::Left(edge_idx);
} else if edge_idx == B - 1 {
middle_kv_idx = B - 1;
insertion = InsertionPlace::Left(edge_idx);
} else if edge_idx == B {
middle_kv_idx = B - 1;
insertion = InsertionPlace::Right(0);
} else {
middle_kv_idx = B;
let new_edge_idx = edge_idx - (B + 1);
insertion = InsertionPlace::Right(new_edge_idx);
match edge_idx {
0..EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER - 1, InsertionPlace::Left(edge_idx)),
EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Left(edge_idx)),
EDGE_IDX_RIGHT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Right(0)),
_ => (KV_IDX_CENTER + 1, InsertionPlace::Right(edge_idx - (KV_IDX_CENTER + 1 + 1))),
}
let mut left_len = middle_kv_idx;
let mut right_len = CAPACITY - middle_kv_idx - 1;
match insertion {
InsertionPlace::Left(edge_idx) => {
debug_assert!(edge_idx <= left_len);
left_len += 1;
}
InsertionPlace::Right(edge_idx) => {
debug_assert!(edge_idx <= right_len);
right_len += 1;
}
}
debug_assert!(left_len >= MIN_LEN);
debug_assert!(right_len >= MIN_LEN);
debug_assert!(left_len + right_len == CAPACITY);
(middle_kv_idx, insertion)
}
impl<'a, K, V, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::Edge> {
@ -1600,3 +1577,6 @@ unsafe fn slice_remove<T>(slice: &mut [T], idx: usize) -> T {
ret
}
}
#[cfg(test)]
mod tests;

View file

@ -0,0 +1,25 @@
use super::*;
#[test]
fn test_splitpoint() {
for idx in 0..=CAPACITY {
let (middle_kv_idx, insertion) = splitpoint(idx);
// Simulate performing the split:
let mut left_len = middle_kv_idx;
let mut right_len = CAPACITY - middle_kv_idx - 1;
match insertion {
InsertionPlace::Left(edge_idx) => {
assert!(edge_idx <= left_len);
left_len += 1;
}
InsertionPlace::Right(edge_idx) => {
assert!(edge_idx <= right_len);
right_len += 1;
}
}
assert!(left_len >= MIN_LEN);
assert!(right_len >= MIN_LEN);
assert!(left_len + right_len == CAPACITY);
}
}

View file

@ -93,6 +93,7 @@
#![feature(container_error_extra)]
#![feature(dropck_eyepatch)]
#![feature(exact_size_is_empty)]
#![feature(exclusive_range_pattern)]
#![feature(extend_one)]
#![feature(fmt_internals)]
#![feature(fn_traits)]