Add ManagedMap::range.
This commit is contained in:
parent
cea6d52b0c
commit
4299b43859
@ -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.
|
||||
|
394
src/map.rs
394
src/map.rs
@ -2,15 +2,16 @@ use core::mem;
|
||||
use core::fmt;
|
||||
use core::slice;
|
||||
use core::borrow::Borrow;
|
||||
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};
|
||||
use std::collections::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut, Range as BTreeRange};
|
||||
#[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 +91,117 @@ impl<T> Into<Option<T>> for RevOption<T> {
|
||||
}
|
||||
}
|
||||
|
||||
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<Self::Item> {
|
||||
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<'a, K, V, Q: 'a, R>(slice: &[Option<(K, V)>], range: R) -> Result<(usize, usize), ()>
|
||||
where K: Ord + Borrow<Q>, Q: Ord + ?Sized, R: RangeBounds<Q>
|
||||
{
|
||||
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
|
||||
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;
|
||||
}
|
||||
}
|
||||
if left == slice.len() || is_before_range!(key!(slice[left])) {
|
||||
return Err(())
|
||||
}
|
||||
left
|
||||
};
|
||||
|
||||
// Find the ending
|
||||
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;
|
||||
}
|
||||
}
|
||||
if right == 0 || is_after_range!(key!(slice[right-1])) {
|
||||
return Err(())
|
||||
}
|
||||
right
|
||||
};
|
||||
|
||||
Ok((begin, end))
|
||||
}
|
||||
|
||||
fn binary_search_by_key<K, V, Q>(slice: &[Option<(K, V)>], key: &Q) -> Result<usize, usize>
|
||||
where K: Ord + Borrow<Q>, Q: Ord + ?Sized
|
||||
{
|
||||
@ -155,6 +267,23 @@ impl<'a, K: Ord + 'a, V: 'a> ManagedMap<'a, K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn range<'b, 'c, Q: 'c, R>(&'b self, range: R) -> Range<'a, K, V>
|
||||
where K: Borrow<Q>, Q: Ord + ?Sized, R: RangeBounds<Q>, 'b: 'a
|
||||
{
|
||||
match self {
|
||||
&ManagedMap::Borrowed(ref pairs) => {
|
||||
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(range))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, key: K, new_value: V) -> Result<Option<V>, (K, V)> {
|
||||
match self {
|
||||
&mut ManagedMap::Borrowed(ref mut pairs) if pairs.len() < 1 =>
|
||||
@ -329,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]
|
||||
@ -398,6 +528,266 @@ 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_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();
|
||||
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();
|
||||
|
Loading…
Reference in New Issue
Block a user