1 use std::collections::BTreeSet; 2 use std::ops::Bound::{self, *}; 3 4 use quickcheck::{quickcheck, TestResult}; 5 6 /// Covers every `std::ops::Range*` plus variants with exclusive start. 7 type RangeAny<T> = (Bound<T>, Bound<T>); 8 9 /// Mimic `RangeBounds::contains`, stabilized in Rust 1.35. 10 trait RangeBounds<T> { contains(&self, _: &T) -> bool11 fn contains(&self, _: &T) -> bool; 12 } 13 14 impl<T: PartialOrd> RangeBounds<T> for RangeAny<T> { contains(&self, item: &T) -> bool15 fn contains(&self, item: &T) -> bool { 16 (match &self.0 { 17 Included(start) => start <= item, 18 Excluded(start) => start < item, 19 Unbounded => true, 20 }) && (match &self.1 { 21 Included(end) => item <= end, 22 Excluded(end) => item < end, 23 Unbounded => true, 24 }) 25 } 26 } 27 28 /// Checks conditions where `BTreeSet::range` panics: 29 /// - Panics if range start > end. 30 /// - Panics if range start == end and both bounds are Excluded. panics<T: PartialOrd>(range: RangeAny<T>) -> bool31 fn panics<T: PartialOrd>(range: RangeAny<T>) -> bool { 32 match (&range.0, &range.1) { 33 (Excluded(start), Excluded(end)) => start >= end, 34 (Included(start), Excluded(end)) 35 | (Excluded(start), Included(end)) 36 | (Included(start), Included(end)) => start > end, 37 (Unbounded, _) | (_, Unbounded) => false, 38 } 39 } 40 41 /// Checks that `BTreeSet::range` returns all items contained in the given `range`. check_range(set: BTreeSet<i32>, range: RangeAny<i32>) -> TestResult42 fn check_range(set: BTreeSet<i32>, range: RangeAny<i32>) -> TestResult { 43 if panics(range) { 44 TestResult::discard() 45 } else { 46 let xs: BTreeSet<_> = set.range(range).cloned().collect(); 47 TestResult::from_bool( 48 set.iter().all(|x| range.contains(x) == xs.contains(x)), 49 ) 50 } 51 } 52 main()53 fn main() { 54 quickcheck(check_range as fn(_, _) -> TestResult); 55 } 56