Skip to content

Commit 56be1ed

Browse files
committed
Add ManagedMap::range.
1 parent 2da4c59 commit 56be1ed

File tree

3 files changed

+296
-2
lines changed

3 files changed

+296
-2
lines changed

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ readme = "README.md"
1010
keywords = ["ownership"]
1111
categories = ["embedded"]
1212
license = "0BSD"
13+
build = "build.rs"
14+
15+
[build-dependencies]
16+
rustc_version = "^0.2"
1317

1418
[features]
1519
std = []

build.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
extern crate rustc_version;
2+
use rustc_version::version;
3+
4+
fn main() {
5+
assert!(version().unwrap().major >= 1);
6+
if version().unwrap().minor < 26 {
7+
println!("cargo:rustc-cfg=RUSTC_RANGEARGUMENT");
8+
}
9+
else {
10+
println!("cargo:rustc-cfg=RUSTC_RANGEBOUNDS");
11+
}
12+
}

src/map.rs

+280-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,17 @@ use core::borrow::Borrow;
66
#[cfg(feature = "std")]
77
use std::collections::BTreeMap;
88
#[cfg(feature = "std")]
9-
use std::collections::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut};
9+
use std::collections::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut, Range as BTreeRange};
10+
#[cfg(feature = "std")]
11+
use std::collections::Bound::{Included, Excluded};
1012
#[cfg(all(feature = "alloc", not(feature = "std")))]
1113
use alloc::btree_map::BTreeMap;
1214
#[cfg(all(feature = "alloc", not(feature = "std")))]
13-
use alloc::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut};
15+
use alloc::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut, Range as BTreeRange};
16+
#[cfg(all(feature = "alloc", not(feature = "std"), RUSTC_RANGEARGUMENT))]
17+
use alloc::Bound::{Included,Excluded}; // Rust < 1.26
18+
#[cfg(all(feature = "alloc", not(feature = "std"), RUSTC_RANGEBOUNDS))]
19+
use core::ops::{Included,Excluded}; // Rust >= 1.26
1420

1521
/// A managed map.
1622
///
@@ -90,6 +96,103 @@ impl<T> Into<Option<T>> for RevOption<T> {
9096
}
9197
}
9298

99+
pub enum Range<'a, 'b, K: 'a, V: 'a> where 'a: 'b {
100+
/// Borrowed variant.
101+
Borrowed(&'b [Option<(K, V)>], usize),
102+
/// Owned variant, only available with the `std` or `alloc` feature enabled.
103+
#[cfg(any(feature = "std", feature = "alloc"))]
104+
Owned(BTreeRange<'b, K, V>),
105+
_Phantom(&'a K),
106+
}
107+
108+
impl<'b, 'a: 'b, K: 'a, V: 'a> Iterator for Range<'a, 'b, K, V> {
109+
type Item = (&'b K, &'b V);
110+
111+
fn next(&mut self) -> Option<Self::Item> {
112+
match *self {
113+
Range::Borrowed(ref slice, ref mut index) => {
114+
*index += 1;
115+
if *index-1 >= slice.len() {
116+
None
117+
}
118+
else {
119+
match slice[*index-1] {
120+
None => None,
121+
Some((ref k, ref v)) => Some((k, v))
122+
}
123+
}
124+
},
125+
#[cfg(any(feature = "std", feature = "alloc"))]
126+
Range::Owned(ref mut range) => range.next(),
127+
Range::_Phantom(_) => unreachable!(),
128+
}
129+
}
130+
}
131+
132+
fn binary_search_by_key_range<K, V, Q>(slice: &[Option<(K, V)>], key_begin: &Q, key_end: &Q) -> Result<(usize, usize), ()>
133+
where K: Ord + Borrow<Q>, Q: Ord + ?Sized
134+
{
135+
if slice.len() == 0 {
136+
return Err(())
137+
}
138+
let (mut left, mut right) = (0, slice.len()-1);
139+
140+
//let key = |entry: Option<(K, V)>| { entry.as_ref().map(|&(ref key, _)| key.borrow()) };
141+
macro_rules! key {
142+
( $e:expr) => { $e.as_ref().map(|&(ref key, _)| key.borrow()) }
143+
}
144+
145+
// We cannot use slice.binary_search_by_key instead of each of the
146+
// two loops here, because we need the left-most match (for begin) and
147+
// the right-most match (for end), and the stdlib does not provide
148+
// any of these guarantees.
149+
150+
// Find the beginning
151+
while left < right {
152+
let middle = left + (right-left)/2;
153+
if key!(slice[middle]) < Some(key_begin) {
154+
left = middle+1;
155+
}
156+
else if middle > 0 && key!(slice[middle-1]) >= Some(key_begin) {
157+
right = middle-1;
158+
}
159+
else {
160+
left = middle;
161+
right = middle;
162+
break;
163+
}
164+
}
165+
assert_eq!(left, right);
166+
let begin = left;
167+
if key!(slice[begin]) < Some(key_begin) {
168+
return Err(())
169+
}
170+
171+
// Find the ending
172+
right = slice.len(); // no need to reset left
173+
while left < right {
174+
let middle = left + (right-left+1)/2;
175+
if key!(slice[middle-1]) >= Some(key_end) {
176+
right = middle-1;
177+
}
178+
else if middle < slice.len() && key!(slice[middle]) < Some(key_end) {
179+
left = middle+1;
180+
}
181+
else {
182+
left = middle;
183+
right = middle;
184+
break;
185+
}
186+
}
187+
assert_eq!(left, right);
188+
let end = right;
189+
if end == 0 || key!(slice[end-1]) > Some(key_end) {
190+
return Err(())
191+
}
192+
193+
Ok((begin, end))
194+
}
195+
93196
fn binary_search_by_key<K, V, Q>(slice: &[Option<(K, V)>], key: &Q) -> Result<usize, usize>
94197
where K: Ord + Borrow<Q>, Q: Ord + ?Sized
95198
{
@@ -155,6 +258,23 @@ impl<'a, K: Ord + 'a, V: 'a> ManagedMap<'a, K, V> {
155258
}
156259
}
157260

261+
pub fn range<'b, 'c, Q>(&'c self, key_begin: &Q, key_end: &Q) -> Range<'a, 'b, K, V>
262+
where K: Borrow<Q>, Q: Ord + ?Sized, 'a: 'b, 'c: 'a
263+
{
264+
match self {
265+
&ManagedMap::Borrowed(ref pairs) => {
266+
match binary_search_by_key_range(&pairs[0..self.len()], key_begin, key_end) {
267+
Ok((begin, end)) => Range::Borrowed(&pairs[begin..end], 0),
268+
Err(()) => Range::Borrowed(&[], 0),
269+
}
270+
},
271+
#[cfg(any(feature = "std", feature = "alloc"))]
272+
&ManagedMap::Owned(ref map) => {
273+
Range::Owned(map.range((Included(key_begin), Excluded(key_end))))
274+
},
275+
}
276+
}
277+
158278
pub fn insert(&mut self, key: K, new_value: V) -> Result<Option<V>, (K, V)> {
159279
match self {
160280
&mut ManagedMap::Borrowed(ref mut pairs) if pairs.len() < 1 =>
@@ -379,6 +499,164 @@ mod test {
379499
assert_eq!(map.get("q"), None);
380500
}
381501

502+
#[test]
503+
fn test_get_none_empty() {
504+
let mut pairs = all_pairs_empty();
505+
let map = ManagedMap::Borrowed(&mut pairs);
506+
assert_eq!(map.len(), 0);
507+
assert!(map.is_empty());
508+
assert_eq!(map.get("q"), None);
509+
}
510+
511+
#[test]
512+
fn test_range_full() {
513+
let mut pairs = all_pairs_full();
514+
let map = ManagedMap::Borrowed(&mut pairs);
515+
assert_eq!(map.len(), 4);
516+
517+
let mut range = map.range("0", "a");
518+
assert_eq!(range.next(), None);
519+
let mut range = map.range("0", "b");
520+
assert_eq!(range.next(), Some((&"a", &1)));
521+
assert_eq!(range.next(), None);
522+
let mut range = map.range("0", "c");
523+
assert_eq!(range.next(), Some((&"a", &1)));
524+
assert_eq!(range.next(), Some((&"b", &2)));
525+
assert_eq!(range.next(), None);
526+
let mut range = map.range("0", "d");
527+
assert_eq!(range.next(), Some((&"a", &1)));
528+
assert_eq!(range.next(), Some((&"b", &2)));
529+
assert_eq!(range.next(), Some((&"c", &3)));
530+
assert_eq!(range.next(), None);
531+
let mut range = map.range("0", "e");
532+
assert_eq!(range.next(), Some((&"a", &1)));
533+
assert_eq!(range.next(), Some((&"b", &2)));
534+
assert_eq!(range.next(), Some((&"c", &3)));
535+
assert_eq!(range.next(), Some((&"d", &4)));
536+
assert_eq!(range.next(), None);
537+
538+
let mut range = map.range("a", "a");
539+
assert_eq!(range.next(), None);
540+
let mut range = map.range("a", "b");
541+
assert_eq!(range.next(), Some((&"a", &1)));
542+
assert_eq!(range.next(), None);
543+
let mut range = map.range("a", "c");
544+
assert_eq!(range.next(), Some((&"a", &1)));
545+
assert_eq!(range.next(), Some((&"b", &2)));
546+
assert_eq!(range.next(), None);
547+
let mut range = map.range("a", "d");
548+
assert_eq!(range.next(), Some((&"a", &1)));
549+
assert_eq!(range.next(), Some((&"b", &2)));
550+
assert_eq!(range.next(), Some((&"c", &3)));
551+
assert_eq!(range.next(), None);
552+
let mut range = map.range("a", "e");
553+
assert_eq!(range.next(), Some((&"a", &1)));
554+
assert_eq!(range.next(), Some((&"b", &2)));
555+
assert_eq!(range.next(), Some((&"c", &3)));
556+
assert_eq!(range.next(), Some((&"d", &4)));
557+
assert_eq!(range.next(), None);
558+
559+
let mut range = map.range("b", "a");
560+
assert_eq!(range.next(), None);
561+
let mut range = map.range("b", "b");
562+
assert_eq!(range.next(), None);
563+
let mut range = map.range("b", "c");
564+
assert_eq!(range.next(), Some((&"b", &2)));
565+
assert_eq!(range.next(), None);
566+
let mut range = map.range("b", "d");
567+
assert_eq!(range.next(), Some((&"b", &2)));
568+
assert_eq!(range.next(), Some((&"c", &3)));
569+
assert_eq!(range.next(), None);
570+
let mut range = map.range("b", "e");
571+
assert_eq!(range.next(), Some((&"b", &2)));
572+
assert_eq!(range.next(), Some((&"c", &3)));
573+
assert_eq!(range.next(), Some((&"d", &4)));
574+
assert_eq!(range.next(), None);
575+
576+
let mut range = map.range("c", "a");
577+
assert_eq!(range.next(), None);
578+
let mut range = map.range("c", "b");
579+
assert_eq!(range.next(), None);
580+
let mut range = map.range("c", "c");
581+
assert_eq!(range.next(), None);
582+
let mut range = map.range("c", "d");
583+
assert_eq!(range.next(), Some((&"c", &3)));
584+
assert_eq!(range.next(), None);
585+
let mut range = map.range("c", "e");
586+
assert_eq!(range.next(), Some((&"c", &3)));
587+
assert_eq!(range.next(), Some((&"d", &4)));
588+
assert_eq!(range.next(), None);
589+
590+
let mut range = map.range("d", "a");
591+
assert_eq!(range.next(), None);
592+
let mut range = map.range("d", "b");
593+
assert_eq!(range.next(), None);
594+
let mut range = map.range("d", "c");
595+
assert_eq!(range.next(), None);
596+
let mut range = map.range("d", "d");
597+
assert_eq!(range.next(), None);
598+
let mut range = map.range("d", "e");
599+
assert_eq!(range.next(), Some((&"d", &4)));
600+
assert_eq!(range.next(), None);
601+
602+
let mut range = map.range("e", "a");
603+
assert_eq!(range.next(), None);
604+
let mut range = map.range("e", "b");
605+
assert_eq!(range.next(), None);
606+
let mut range = map.range("e", "c");
607+
assert_eq!(range.next(), None);
608+
let mut range = map.range("e", "d");
609+
assert_eq!(range.next(), None);
610+
let mut range = map.range("e", "e");
611+
assert_eq!(range.next(), None);
612+
}
613+
614+
#[test]
615+
fn test_range_one_pair() {
616+
let mut pairs = one_pair_full();
617+
let map = ManagedMap::Borrowed(&mut pairs);
618+
assert_eq!(map.len(), 1);
619+
620+
let mut range = map.range("0", "a");
621+
assert_eq!(range.next(), None);
622+
let mut range = map.range("0", "b");
623+
assert_eq!(range.next(), Some((&"a", &1)));
624+
assert_eq!(range.next(), None);
625+
let mut range = map.range("0", "c");
626+
assert_eq!(range.next(), Some((&"a", &1)));
627+
assert_eq!(range.next(), None);
628+
629+
let mut range = map.range("a", "a");
630+
assert_eq!(range.next(), None);
631+
let mut range = map.range("a", "b");
632+
assert_eq!(range.next(), Some((&"a", &1)));
633+
assert_eq!(range.next(), None);
634+
let mut range = map.range("a", "c");
635+
assert_eq!(range.next(), Some((&"a", &1)));
636+
assert_eq!(range.next(), None);
637+
638+
let mut range = map.range("b", "a");
639+
assert_eq!(range.next(), None);
640+
let mut range = map.range("b", "b");
641+
assert_eq!(range.next(), None);
642+
let mut range = map.range("b", "c");
643+
assert_eq!(range.next(), None);
644+
}
645+
646+
#[test]
647+
fn test_range_empty() {
648+
let mut pairs = all_pairs_empty();
649+
let map = ManagedMap::Borrowed(&mut pairs);
650+
assert_eq!(map.len(), 0);
651+
652+
let mut range = map.range("b", "a");
653+
assert_eq!(range.next(), None);
654+
let mut range = map.range("b", "b");
655+
assert_eq!(range.next(), None);
656+
let mut range = map.range("b", "c");
657+
assert_eq!(range.next(), None);
658+
}
659+
382660
#[test]
383661
fn test_get_mut_some() {
384662
let mut pairs = all_pairs_full();

0 commit comments

Comments
 (0)