From 63e49b38a1b10437c2867eaed540571c6ad3a293 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Thu, 17 May 2018 19:32:51 +0200 Subject: [PATCH 1/3] Add ManagedMap::range. --- src/map.rs | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 266 insertions(+), 2 deletions(-) diff --git a/src/map.rs b/src/map.rs index a9614a7..d496c24 100644 --- a/src/map.rs +++ b/src/map.rs @@ -2,15 +2,19 @@ use core::mem; use core::fmt; use core::slice; use core::borrow::Borrow; +#[cfg(all(feature = "alloc", not(feature = "std")))] +use core::ops::Bound::{Included,Excluded}; #[cfg(feature = "std")] use std::collections::BTreeMap; #[cfg(feature = "std")] -use std::collections::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut}; +use std::collections::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut, Range as BTreeRange}; +#[cfg(feature = "std")] +use std::collections::Bound::{Included, Excluded}; #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::btree_map::BTreeMap; #[cfg(all(feature = "alloc", not(feature = "std")))] -use alloc::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut}; +use alloc::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut, Range as BTreeRange}; /// A managed map. /// @@ -90,6 +94,91 @@ impl Into> for RevOption { } } +pub enum Range<'a, K: 'a, V: 'a> { + /// Borrowed variant. + Borrowed(&'a [Option<(K, V)>], usize), + /// Owned variant, only available with the `std` or `alloc` feature enabled. + #[cfg(any(feature = "std", feature = "alloc"))] + Owned(BTreeRange<'a, K, V>), +} + +impl<'a, K: 'a, V: 'a> Iterator for Range<'a, K, V> { + type Item = (&'a K, &'a V); + + fn next(&mut self) -> Option { + match *self { + Range::Borrowed(ref slice, ref mut index) => { + *index += 1; + if *index-1 >= slice.len() { + None + } else { + match slice[*index-1] { + None => None, + Some((ref k, ref v)) => Some((k, v)) + } + } + }, + #[cfg(any(feature = "std", feature = "alloc"))] + Range::Owned(ref mut range) => range.next(), + } + } +} + +fn binary_search_by_key_range(slice: &[Option<(K, V)>], key_begin: &Q, key_end: &Q) -> Result<(usize, usize), ()> + where K: Ord + Borrow, Q: Ord + ?Sized +{ + if slice.len() == 0 { + return Err(()) + } + let (mut left, mut right) = (0, slice.len()-1); + + macro_rules! key { + ( $e:expr) => { $e.as_ref().map(|&(ref key, _)| key.borrow()) } + } + + // We cannot use slice.binary_search_by_key instead of each of the + // two loops here, because we need the left-most match (for begin) and + // the right-most match (for end), and the stdlib does not provide + // any of these guarantees. + + // Find the beginning + while left < right { + let middle = left + (right-left)/2; + if key!(slice[middle]) < Some(key_begin) { + left = middle+1; + } else if middle > 0 && key!(slice[middle-1]) >= Some(key_begin) { + right = middle-1; + } else { + left = middle; + break; + } + } + let begin = left; + if key!(slice[begin]) < Some(key_begin) { + return Err(()) + } + + // Find the ending + right = slice.len(); // no need to reset left + while left < right { + let middle = left + (right-left+1)/2; + if key!(slice[middle-1]) >= Some(key_end) { + right = middle-1; + } else if middle < slice.len() && key!(slice[middle]) < Some(key_end) { + left = middle+1; + } else { + right = middle; + break; + } + } + let end = right; + if end == 0 || key!(slice[end-1]) > Some(key_end) { + return Err(()) + } + + Ok((begin, end)) +} + fn binary_search_by_key(slice: &[Option<(K, V)>], key: &Q) -> Result where K: Ord + Borrow, Q: Ord + ?Sized { @@ -155,6 +244,23 @@ impl<'a, K: Ord + 'a, V: 'a> ManagedMap<'a, K, V> { } } + pub fn range<'b, Q>(&'b self, key_begin: &Q, key_end: &Q) -> Range<'a, K, V> + where K: Borrow, Q: Ord + ?Sized, 'b: 'a + { + match self { + &ManagedMap::Borrowed(ref pairs) => { + match binary_search_by_key_range(&pairs[0..self.len()], key_begin, key_end) { + Ok((begin, end)) => Range::Borrowed(&pairs[begin..end], 0), + Err(()) => Range::Borrowed(&[], 0), + } + }, + #[cfg(any(feature = "std", feature = "alloc"))] + &ManagedMap::Owned(ref map) => { + Range::Owned(map.range((Included(key_begin), Excluded(key_end)))) + }, + } + } + pub fn insert(&mut self, key: K, new_value: V) -> Result, (K, V)> { match self { &mut ManagedMap::Borrowed(ref mut pairs) if pairs.len() < 1 => @@ -379,6 +485,164 @@ mod test { assert_eq!(map.get("q"), None); } + #[test] + fn test_get_none_empty() { + let mut pairs = all_pairs_empty(); + let map = ManagedMap::Borrowed(&mut pairs); + assert_eq!(map.len(), 0); + assert!(map.is_empty()); + assert_eq!(map.get("q"), None); + } + + #[test] + fn test_range_full() { + let mut pairs = all_pairs_full(); + let map = ManagedMap::Borrowed(&mut pairs); + assert_eq!(map.len(), 4); + + let mut range = map.range("0", "a"); + assert_eq!(range.next(), None); + let mut range = map.range("0", "b"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), None); + let mut range = map.range("0", "c"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), None); + let mut range = map.range("0", "d"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), None); + let mut range = map.range("0", "e"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), Some((&"d", &4))); + assert_eq!(range.next(), None); + + let mut range = map.range("a", "a"); + assert_eq!(range.next(), None); + let mut range = map.range("a", "b"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), None); + let mut range = map.range("a", "c"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), None); + let mut range = map.range("a", "d"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), None); + let mut range = map.range("a", "e"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), Some((&"d", &4))); + assert_eq!(range.next(), None); + + let mut range = map.range("b", "a"); + assert_eq!(range.next(), None); + let mut range = map.range("b", "b"); + assert_eq!(range.next(), None); + let mut range = map.range("b", "c"); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), None); + let mut range = map.range("b", "d"); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), None); + let mut range = map.range("b", "e"); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), Some((&"d", &4))); + assert_eq!(range.next(), None); + + let mut range = map.range("c", "a"); + assert_eq!(range.next(), None); + let mut range = map.range("c", "b"); + assert_eq!(range.next(), None); + let mut range = map.range("c", "c"); + assert_eq!(range.next(), None); + let mut range = map.range("c", "d"); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), None); + let mut range = map.range("c", "e"); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), Some((&"d", &4))); + assert_eq!(range.next(), None); + + let mut range = map.range("d", "a"); + assert_eq!(range.next(), None); + let mut range = map.range("d", "b"); + assert_eq!(range.next(), None); + let mut range = map.range("d", "c"); + assert_eq!(range.next(), None); + let mut range = map.range("d", "d"); + assert_eq!(range.next(), None); + let mut range = map.range("d", "e"); + assert_eq!(range.next(), Some((&"d", &4))); + assert_eq!(range.next(), None); + + let mut range = map.range("e", "a"); + assert_eq!(range.next(), None); + let mut range = map.range("e", "b"); + assert_eq!(range.next(), None); + let mut range = map.range("e", "c"); + assert_eq!(range.next(), None); + let mut range = map.range("e", "d"); + assert_eq!(range.next(), None); + let mut range = map.range("e", "e"); + assert_eq!(range.next(), None); + } + + #[test] + fn test_range_one_pair() { + let mut pairs = one_pair_full(); + let map = ManagedMap::Borrowed(&mut pairs); + assert_eq!(map.len(), 1); + + let mut range = map.range("0", "a"); + assert_eq!(range.next(), None); + let mut range = map.range("0", "b"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), None); + let mut range = map.range("0", "c"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), None); + + let mut range = map.range("a", "a"); + assert_eq!(range.next(), None); + let mut range = map.range("a", "b"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), None); + let mut range = map.range("a", "c"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), None); + + let mut range = map.range("b", "a"); + assert_eq!(range.next(), None); + let mut range = map.range("b", "b"); + assert_eq!(range.next(), None); + let mut range = map.range("b", "c"); + assert_eq!(range.next(), None); + } + + #[test] + fn test_range_empty() { + let mut pairs = all_pairs_empty(); + let map = ManagedMap::Borrowed(&mut pairs); + assert_eq!(map.len(), 0); + + let mut range = map.range("b", "a"); + assert_eq!(range.next(), None); + let mut range = map.range("b", "b"); + assert_eq!(range.next(), None); + let mut range = map.range("b", "c"); + assert_eq!(range.next(), None); + } + #[test] fn test_get_mut_some() { let mut pairs = all_pairs_full(); From f70bcd010e2d4d14b49f12cdc10fc58af7f3d22d Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Sat, 19 May 2018 13:24:31 +0200 Subject: [PATCH 2/3] ManagedMap::range: use RangeBounds, like BTreeMap::range. --- src/lib.rs | 1 + src/map.rs | 185 ++++++++++++++++++++++++++++++----------------------- 2 files changed, 105 insertions(+), 81 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b1a71a9..320edd0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ #![no_std] #![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))] #![cfg_attr(feature = "map", feature(slice_rotate))] +#![cfg_attr(feature = "map", feature(collections_range))] //! A library that provides a way to logically own objects, whether or not //! heap allocation is available. diff --git a/src/map.rs b/src/map.rs index d496c24..422a974 100644 --- a/src/map.rs +++ b/src/map.rs @@ -2,15 +2,12 @@ use core::mem; use core::fmt; use core::slice; use core::borrow::Borrow; -#[cfg(all(feature = "alloc", not(feature = "std")))] -use core::ops::Bound::{Included,Excluded}; +use core::ops::{Bound, RangeBounds}; #[cfg(feature = "std")] use std::collections::BTreeMap; #[cfg(feature = "std")] use std::collections::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut, Range as BTreeRange}; -#[cfg(feature = "std")] -use std::collections::Bound::{Included, Excluded}; #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::btree_map::BTreeMap; #[cfg(all(feature = "alloc", not(feature = "std")))] @@ -124,8 +121,8 @@ impl<'a, K: 'a, V: 'a> Iterator for Range<'a, K, V> { } } -fn binary_search_by_key_range(slice: &[Option<(K, V)>], key_begin: &Q, key_end: &Q) -> Result<(usize, usize), ()> - where K: Ord + Borrow, Q: Ord + ?Sized +fn binary_search_by_key_range<'a, K, V, Q: 'a, R>(slice: &[Option<(K, V)>], range: R) -> Result<(usize, usize), ()> + where K: Ord + Borrow, Q: Ord + ?Sized, R: RangeBounds { if slice.len() == 0 { return Err(()) @@ -142,39 +139,65 @@ fn binary_search_by_key_range(slice: &[Option<(K, V)>], key_begin: &Q, // any of these guarantees. // Find the beginning - while left < right { - let middle = left + (right-left)/2; - if key!(slice[middle]) < Some(key_begin) { - left = middle+1; - } else if middle > 0 && key!(slice[middle-1]) >= Some(key_begin) { - right = middle-1; - } else { - left = middle; - break; + let begin = if let Bound::Unbounded = range.start() { + 0 + } else { + macro_rules! is_before_range { + ( $item: expr) => { + match &range.start() { + Bound::Included(ref key_begin) => $item < Some(key_begin.borrow()), + Bound::Excluded(ref key_begin) => $item <= Some(key_begin.borrow()), + Bound::Unbounded => unreachable!(), + } + } + }; + while left < right { + let middle = left + (right-left)/2; + if is_before_range!(key!(slice[middle])) { + left = middle+1; + } else if middle > 0 && !is_before_range!(key!(slice[middle-1])) { + right = middle-1; + } else { + left = middle; + break; + } } - } - let begin = left; - if key!(slice[begin]) < Some(key_begin) { - return Err(()) - } + if left == slice.len() || is_before_range!(key!(slice[left])) { + return Err(()) + } + left + }; // Find the ending - right = slice.len(); // no need to reset left - while left < right { - let middle = left + (right-left+1)/2; - if key!(slice[middle-1]) >= Some(key_end) { - right = middle-1; - } else if middle < slice.len() && key!(slice[middle]) < Some(key_end) { - left = middle+1; - } else { - right = middle; - break; + let end = if let Bound::Unbounded = range.end() { + slice.len() + } else { + macro_rules! is_after_range { + ( $item:expr ) => { + match &range.end() { + Bound::Included(ref key_end) => $item > Some(key_end.borrow()), + Bound::Excluded(ref key_end) => $item >= Some(key_end.borrow()), + Bound::Unbounded => unreachable!(), + } + } + }; + right = slice.len(); // no need to reset left + while left < right { + let middle = left + (right-left+1)/2; + if is_after_range!(key!(slice[middle-1])) { + right = middle-1; + } else if middle < slice.len() && !is_after_range!(key!(slice[middle])) { + left = middle+1; + } else { + right = middle; + break; + } } - } - let end = right; - if end == 0 || key!(slice[end-1]) > Some(key_end) { - return Err(()) - } + if right == 0 || is_after_range!(key!(slice[right-1])) { + return Err(()) + } + right + }; Ok((begin, end)) } @@ -244,19 +267,19 @@ impl<'a, K: Ord + 'a, V: 'a> ManagedMap<'a, K, V> { } } - pub fn range<'b, Q>(&'b self, key_begin: &Q, key_end: &Q) -> Range<'a, K, V> - where K: Borrow, Q: Ord + ?Sized, 'b: 'a + pub fn range<'b, 'c, Q: 'c, R>(&'b self, range: R) -> Range<'a, K, V> + where K: Borrow, Q: Ord + ?Sized, R: RangeBounds, 'b: 'a { match self { &ManagedMap::Borrowed(ref pairs) => { - match binary_search_by_key_range(&pairs[0..self.len()], key_begin, key_end) { + match binary_search_by_key_range(&pairs[0..self.len()], range) { Ok((begin, end)) => Range::Borrowed(&pairs[begin..end], 0), Err(()) => Range::Borrowed(&[], 0), } }, #[cfg(any(feature = "std", feature = "alloc"))] &ManagedMap::Owned(ref map) => { - Range::Owned(map.range((Included(key_begin), Excluded(key_end)))) + Range::Owned(map.range(range)) }, } } @@ -500,100 +523,100 @@ mod test { let map = ManagedMap::Borrowed(&mut pairs); assert_eq!(map.len(), 4); - let mut range = map.range("0", "a"); + let mut range = map.range("0".."a"); assert_eq!(range.next(), None); - let mut range = map.range("0", "b"); + let mut range = map.range("0".."b"); assert_eq!(range.next(), Some((&"a", &1))); assert_eq!(range.next(), None); - let mut range = map.range("0", "c"); + let mut range = map.range("0".."c"); assert_eq!(range.next(), Some((&"a", &1))); assert_eq!(range.next(), Some((&"b", &2))); assert_eq!(range.next(), None); - let mut range = map.range("0", "d"); + let mut range = map.range("0".."d"); assert_eq!(range.next(), Some((&"a", &1))); assert_eq!(range.next(), Some((&"b", &2))); assert_eq!(range.next(), Some((&"c", &3))); assert_eq!(range.next(), None); - let mut range = map.range("0", "e"); + let mut range = map.range("0".."e"); assert_eq!(range.next(), Some((&"a", &1))); assert_eq!(range.next(), Some((&"b", &2))); assert_eq!(range.next(), Some((&"c", &3))); assert_eq!(range.next(), Some((&"d", &4))); assert_eq!(range.next(), None); - let mut range = map.range("a", "a"); + let mut range = map.range("a".."a"); assert_eq!(range.next(), None); - let mut range = map.range("a", "b"); + let mut range = map.range("a".."b"); assert_eq!(range.next(), Some((&"a", &1))); assert_eq!(range.next(), None); - let mut range = map.range("a", "c"); + let mut range = map.range("a".."c"); assert_eq!(range.next(), Some((&"a", &1))); assert_eq!(range.next(), Some((&"b", &2))); assert_eq!(range.next(), None); - let mut range = map.range("a", "d"); + let mut range = map.range("a".."d"); assert_eq!(range.next(), Some((&"a", &1))); assert_eq!(range.next(), Some((&"b", &2))); assert_eq!(range.next(), Some((&"c", &3))); assert_eq!(range.next(), None); - let mut range = map.range("a", "e"); + let mut range = map.range("a".."e"); assert_eq!(range.next(), Some((&"a", &1))); assert_eq!(range.next(), Some((&"b", &2))); assert_eq!(range.next(), Some((&"c", &3))); assert_eq!(range.next(), Some((&"d", &4))); assert_eq!(range.next(), None); - let mut range = map.range("b", "a"); + let mut range = map.range("b".."a"); assert_eq!(range.next(), None); - let mut range = map.range("b", "b"); + let mut range = map.range("b".."b"); assert_eq!(range.next(), None); - let mut range = map.range("b", "c"); + let mut range = map.range("b".."c"); assert_eq!(range.next(), Some((&"b", &2))); assert_eq!(range.next(), None); - let mut range = map.range("b", "d"); + let mut range = map.range("b".."d"); assert_eq!(range.next(), Some((&"b", &2))); assert_eq!(range.next(), Some((&"c", &3))); assert_eq!(range.next(), None); - let mut range = map.range("b", "e"); + let mut range = map.range("b".."e"); assert_eq!(range.next(), Some((&"b", &2))); assert_eq!(range.next(), Some((&"c", &3))); assert_eq!(range.next(), Some((&"d", &4))); assert_eq!(range.next(), None); - let mut range = map.range("c", "a"); + let mut range = map.range("c".."a"); assert_eq!(range.next(), None); - let mut range = map.range("c", "b"); + let mut range = map.range("c".."b"); assert_eq!(range.next(), None); - let mut range = map.range("c", "c"); + let mut range = map.range("c".."c"); assert_eq!(range.next(), None); - let mut range = map.range("c", "d"); + let mut range = map.range("c".."d"); assert_eq!(range.next(), Some((&"c", &3))); assert_eq!(range.next(), None); - let mut range = map.range("c", "e"); + let mut range = map.range("c".."e"); assert_eq!(range.next(), Some((&"c", &3))); assert_eq!(range.next(), Some((&"d", &4))); assert_eq!(range.next(), None); - let mut range = map.range("d", "a"); + let mut range = map.range("d".."a"); assert_eq!(range.next(), None); - let mut range = map.range("d", "b"); + let mut range = map.range("d".."b"); assert_eq!(range.next(), None); - let mut range = map.range("d", "c"); + let mut range = map.range("d".."c"); assert_eq!(range.next(), None); - let mut range = map.range("d", "d"); + let mut range = map.range("d".."d"); assert_eq!(range.next(), None); - let mut range = map.range("d", "e"); + let mut range = map.range("d".."e"); assert_eq!(range.next(), Some((&"d", &4))); assert_eq!(range.next(), None); - let mut range = map.range("e", "a"); + let mut range = map.range("e".."a"); assert_eq!(range.next(), None); - let mut range = map.range("e", "b"); + let mut range = map.range("e".."b"); assert_eq!(range.next(), None); - let mut range = map.range("e", "c"); + let mut range = map.range("e".."c"); assert_eq!(range.next(), None); - let mut range = map.range("e", "d"); + let mut range = map.range("e".."d"); assert_eq!(range.next(), None); - let mut range = map.range("e", "e"); + let mut range = map.range("e".."e"); assert_eq!(range.next(), None); } @@ -603,29 +626,29 @@ mod test { let map = ManagedMap::Borrowed(&mut pairs); assert_eq!(map.len(), 1); - let mut range = map.range("0", "a"); + let mut range = map.range("0".."a"); assert_eq!(range.next(), None); - let mut range = map.range("0", "b"); + let mut range = map.range("0".."b"); assert_eq!(range.next(), Some((&"a", &1))); assert_eq!(range.next(), None); - let mut range = map.range("0", "c"); + let mut range = map.range("0".."c"); assert_eq!(range.next(), Some((&"a", &1))); assert_eq!(range.next(), None); - let mut range = map.range("a", "a"); + let mut range = map.range("a".."a"); assert_eq!(range.next(), None); - let mut range = map.range("a", "b"); + let mut range = map.range("a".."b"); assert_eq!(range.next(), Some((&"a", &1))); assert_eq!(range.next(), None); - let mut range = map.range("a", "c"); + let mut range = map.range("a".."c"); assert_eq!(range.next(), Some((&"a", &1))); assert_eq!(range.next(), None); - let mut range = map.range("b", "a"); + let mut range = map.range("b".."a"); assert_eq!(range.next(), None); - let mut range = map.range("b", "b"); + let mut range = map.range("b".."b"); assert_eq!(range.next(), None); - let mut range = map.range("b", "c"); + let mut range = map.range("b".."c"); assert_eq!(range.next(), None); } @@ -635,11 +658,11 @@ mod test { let map = ManagedMap::Borrowed(&mut pairs); assert_eq!(map.len(), 0); - let mut range = map.range("b", "a"); + let mut range = map.range("b".."a"); assert_eq!(range.next(), None); - let mut range = map.range("b", "b"); + let mut range = map.range("b".."b"); assert_eq!(range.next(), None); - let mut range = map.range("b", "c"); + let mut range = map.range("b".."c"); assert_eq!(range.next(), None); } From 10f767c9a4c68f392d7ab8830b361d3727ae0389 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Sat, 19 May 2018 13:40:52 +0200 Subject: [PATCH 3/3] Add tests. --- src/map.rs | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/src/map.rs b/src/map.rs index 422a974..2f3c8d4 100644 --- a/src/map.rs +++ b/src/map.rs @@ -458,6 +458,7 @@ impl<'a, K: Ord + 'a, V: 'a> Iterator for IterMut<'a, K, V> { #[cfg(test)] mod test { use super::ManagedMap; + use core::ops::Bound::*; fn all_pairs_empty() -> [Option<(&'static str, u32)>; 4] { [None; 4] @@ -517,6 +518,108 @@ mod test { assert_eq!(map.get("q"), None); } + #[test] + fn test_range_full_unbounded() { + let mut pairs = all_pairs_full(); + let map = ManagedMap::Borrowed(&mut pairs); + assert_eq!(map.len(), 4); + + let mut range = map.range("a"..); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), Some((&"d", &4))); + assert_eq!(range.next(), None); + + let mut range = map.range("b"..); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), Some((&"d", &4))); + assert_eq!(range.next(), None); + + let mut range = map.range("d"..); + assert_eq!(range.next(), Some((&"d", &4))); + assert_eq!(range.next(), None); + + let mut range = map.range(.."e"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), Some((&"d", &4))); + assert_eq!(range.next(), None); + + let mut range = map.range(.."d"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), None); + + let mut range = map.range(.."b"); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), None); + + let mut range = map.range(.."a"); + assert_eq!(range.next(), None); + + let mut range = map.range::<&str, _>(..); + assert_eq!(range.next(), Some((&"a", &1))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), Some((&"d", &4))); + assert_eq!(range.next(), None); + } + + #[test] + fn test_range_full_exclude_left() { + let mut pairs = all_pairs_full(); + let map = ManagedMap::Borrowed(&mut pairs); + assert_eq!(map.len(), 4); + + let mut range = map.range::<&str, _>((Excluded("a"), Excluded("a"))); + assert_eq!(range.next(), None); + let mut range = map.range::<&str, _>((Excluded("a"), Excluded("b"))); + assert_eq!(range.next(), None); + let mut range = map.range::<&str, _>((Excluded("a"), Excluded("c"))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), None); + let mut range = map.range::<&str, _>((Excluded("a"), Excluded("d"))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), None); + let mut range = map.range::<&str, _>((Excluded("a"), Excluded("e"))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), Some((&"d", &4))); + assert_eq!(range.next(), None); + } + + #[test] + fn test_range_full_include_right() { + let mut pairs = all_pairs_full(); + let map = ManagedMap::Borrowed(&mut pairs); + assert_eq!(map.len(), 4); + + let mut range = map.range::<&str, _>((Included("b"), Included("a"))); + assert_eq!(range.next(), None); + let mut range = map.range::<&str, _>((Included("b"), Included("b"))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), None); + let mut range = map.range::<&str, _>((Included("b"), Included("c"))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), None); + let mut range = map.range::<&str, _>((Included("b"), Included("d"))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), Some((&"d", &4))); + assert_eq!(range.next(), None); + let mut range = map.range::<&str, _>((Included("b"), Included("e"))); + assert_eq!(range.next(), Some((&"b", &2))); + assert_eq!(range.next(), Some((&"c", &3))); + assert_eq!(range.next(), Some((&"d", &4))); + assert_eq!(range.next(), None); + } + #[test] fn test_range_full() { let mut pairs = all_pairs_full();