From 421e0ff3d9aab9f0a1d262d9b4e0f34b49eb2465 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Fri, 14 Aug 2020 14:50:30 +0200 Subject: [PATCH] BTreeMap: refactor splitpoint and move testing over to unit test --- library/alloc/src/collections/btree/node.rs | 42 +++++-------------- .../alloc/src/collections/btree/node/tests.rs | 25 +++++++++++ library/alloc/src/lib.rs | 1 + 3 files changed, 37 insertions(+), 31 deletions(-) create mode 100644 library/alloc/src/collections/btree/node/tests.rs diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index aa959c667ac..5a6a71c5fb6 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -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, K, V, NodeType>, marker::Edge> { @@ -1594,3 +1571,6 @@ unsafe fn slice_remove(slice: &mut [T], idx: usize) -> T { ret } } + +#[cfg(test)] +mod tests; diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs new file mode 100644 index 00000000000..e2416974ddc --- /dev/null +++ b/library/alloc/src/collections/btree/node/tests.rs @@ -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); + } +} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 9ac23886d4e..75a2c6be41c 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -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)]