// Copyright 2015 Joe Neeman. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. extern crate num_traits; #[cfg(test)] extern crate num_iter; #[cfg(test)] extern crate quickcheck; use num_traits::PrimInt; use std::cmp::{max, min, Ordering}; use std::fmt::{Debug, Formatter}; use std::iter::FromIterator; use std::{mem, usize}; const DISPLAY_LIMIT: usize = 10; /// A range of elements, including the endpoints. #[derive(Copy, Clone, Hash, PartialEq, PartialOrd, Eq, Ord)] pub struct Range { pub start: T, pub end: T, } impl Debug for Range { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { try!(self.start.fmt(f)); try!(f.write_str(" -- ")); try!(self.end.fmt(f)); Ok(()) } } impl Range { /// Creates a new range with the given start and endpoints (inclusive). /// /// # Panics /// - if `start` is strictly larger than `end` pub fn new(start: T, end: T) -> Range { if start > end { panic!("Ranges must be ordered"); } Range { start: start, end: end, } } /// Creates a new range containing everything. pub fn full() -> Range { Range { start: T::min_value(), end: T::max_value(), } } /// Creates a new range containing a single thing. pub fn single(x: T) -> Range { Range::new(x, x) } /// Tests whether a given element belongs to this range. pub fn contains(&self, x: T) -> bool { self.start <= x && x <= self.end } /// Checks whether the intersections overlap. pub fn intersects(&self, other: &Self) -> bool { self.start <= other.end && self.end >= other.start } /// Computes the intersection between two ranges. Returns none if the intersection is empty. pub fn intersection(&self, other: &Self) -> Option { if self.intersects(other) { Some(Range::new( max(self.start, other.start), min(self.end, other.end), )) } else { None } } /// Returns the smallest range that covers `self` and `other`. pub fn cover(&self, other: &Self) -> Self { Range::new(min(self.start, other.start), max(self.end, other.end)) } } impl PartialEq for Range { fn eq(&self, x: &T) -> bool { self.contains(*x) } } impl PartialOrd for Range { fn partial_cmp(&self, x: &T) -> Option { if self.end < *x { Some(Ordering::Less) } else if self.start > *x { Some(Ordering::Greater) } else { Some(Ordering::Equal) } } } /// When creating a [`RangeMap`] from a list of ranges and values, there's a possiblity that two /// ranges will overlap. In this case, it's a problem if they want to be associated to different /// values (because we don't know which value should be assigned to the intersection of the /// ranges). An `OverlapError` is the result of such a situation. It contains two members. The /// first is a [`RangeMap`] obtained by simply ignoring all the ranges that would cause a bad /// overlap. The second is the collection of ranges that were ignored. // TODO: an example #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct OverlapError { pub non_overlapping: RangeMap, pub discarded: Vec<(Range, V)>, } /// A set of characters. Optionally, each character in the set may be associated with some data. #[derive(Clone, Eq, Hash, PartialEq)] pub struct RangeMap { elts: Vec<(Range, V)>, } impl Debug for RangeMap { // When alternate formatting is specified, only prints out the first bunch of mappings. fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { try!(f.write_fmt(format_args!("RangeMap ("))); if f.alternate() { try!(f .debug_map() .entries(self.elts.iter().map(|x| (&x.0, &x.1)).take(DISPLAY_LIMIT)) .finish()); if self.elts.len() > DISPLAY_LIMIT { try!(f.write_str("...")); } } else { try!(f .debug_map() .entries(self.elts.iter().map(|x| (&x.0, &x.1))) .finish()); } try!(f.write_str(")")); Ok(()) } } impl FromIterator<(Range, V)> for RangeMap { /// Builds a `RangeMap` from an iterator over pairs. If any ranges overlap, they must map to /// the same value. /// /// # Panics /// Panics if there are ranges that overlap and do not map to the same value. If you are not /// sure whether this could happen, use [`RangeMap::try_from_iter`] instead. fn from_iter, V)>>(iter: I) -> Self { RangeMap::try_from_iter(iter).ok().unwrap() } } impl RangeMap { /// Creates a new empty `RangeMap`. pub fn new() -> RangeMap { RangeMap { elts: Vec::new() } } /// Builds a `RangeMap` from an iterator over pairs. If any ranges overlap, they should map to /// the same value. If not, returns an [`OverlapError`]. pub fn try_from_iter, V)>>( iter: I, ) -> Result, OverlapError> { let mut vec: Vec<_> = iter.into_iter().collect(); vec.sort_by(|x, y| x.0.cmp(&y.0)); let mut ret = RangeMap { elts: vec }; let discarded = ret.normalize(); if discarded.is_empty() { Ok(ret) } else { Err(OverlapError { non_overlapping: ret, discarded: discarded, }) } } // Creates a `RangeMap` from a `Vec`, which must contain ranges in ascending order. If any // ranges overlap, they must map to the same value. // // Panics if the ranges are not sorted, or if they overlap without mapping to the same value. fn from_sorted_vec(vec: Vec<(Range, V)>) -> RangeMap { let mut ret = RangeMap { elts: vec }; ret.normalize(); ret } // Creates a RangeMap from a Vec, which must be sorted and normalized. // // Panics unless `vec` is sorted and normalized. fn from_norm_vec(vec: Vec<(Range, V)>) -> RangeMap { for i in 1..vec.len() { if vec[i].0.start <= vec[i - 1].0.end { panic!( "vector {:?} has overlapping ranges {:?} and {:?}", vec, vec[i - 1], vec[i] ); } // If vec[i-1].0.end is T::max_value() then we've already panicked, so the unwrap is // safe. if vec[i].0.start == vec[i - 1].0.end.checked_add(&T::one()).unwrap() && vec[i].1 == vec[i - 1].1 { panic!( "vector {:?} has adjacent ranges with same value {:?} and {:?}", vec, vec[i - 1], vec[i] ); } } RangeMap { elts: vec } } /// Returns the number of mapped ranges. /// /// Note that this is not usually the same as the number of mapped values. pub fn num_ranges(&self) -> usize { self.elts.len() } /// Tests whether this map is empty. pub fn is_empty(&self) -> bool { self.elts.is_empty() } /// Tests whether this `CharMap` maps every value. pub fn is_full(&self) -> bool { let mut last_end = T::min_value(); for &(range, _) in &self.elts { if range.start > last_end { return false; } last_end = range.end; } last_end == T::max_value() } /// Iterates over all the mapped ranges and values. pub fn ranges_values<'a>(&'a self) -> std::slice::Iter<'a, (Range, V)> { self.elts.iter() } /// Iterates over all mappings. pub fn keys_values<'a>(&'a self) -> PairIter<'a, T, V> { PairIter { map: self, next_range_idx: if self.is_empty() { None } else { Some(0) }, next_key: if self.is_empty() { T::min_value() } else { self.elts[0].0.start }, } } /// Finds the value that `x` maps to, if it exists. /// /// Runs in `O(log n)` time, where `n` is the number of mapped ranges. pub fn get(&self, x: T) -> Option<&V> { self.elts // The unwrap is ok because Range::partial_cmp(&T) never returns None. .binary_search_by(|r| r.0.partial_cmp(&x).unwrap()) .ok() .map(|idx| &self.elts[idx].1) } // Minimizes the number of ranges in this map. // // If there are any overlapping ranges that map to the same data, merges them. Assumes that the // ranges are sorted according to their start. // // If there are overlapping ranges that map to different values, we delete them. The return // value is the collection of all ranges that were deleted. // // TODO: because the output is always smaller than the input, this could be done in-place. fn normalize(&mut self) -> Vec<(Range, V)> { let mut vec = Vec::with_capacity(self.elts.len()); let mut discarded = Vec::new(); mem::swap(&mut vec, &mut self.elts); for (range, val) in vec.into_iter() { if let Some(&mut (ref mut last_range, ref last_val)) = self.elts.last_mut() { if range.start <= last_range.end && &val != last_val { discarded.push((range, val)); continue; } if range.start <= last_range.end.saturating_add(T::one()) && &val == last_val { last_range.end = max(range.end, last_range.end); continue; } } self.elts.push((range, val)); } discarded } /// Returns those mappings whose keys belong to the given set. pub fn intersection(&self, other: &RangeSet) -> RangeMap { let mut ret = Vec::new(); let mut other_iter = other.map.elts.iter().peekable(); for &(ref r, ref data) in &self.elts { while let Some(&&(ref s, _)) = other_iter.peek() { if let Some(int) = s.intersection(r) { ret.push((int, data.clone())); } if s.end >= r.end { break; } else { other_iter.next(); } } } RangeMap::from_sorted_vec(ret) } /// Counts the number of mapped keys. /// /// This saturates at `usize::MAX`. pub fn num_keys(&self) -> usize { self.ranges_values().fold(0, |acc, range| { acc.saturating_add( (range.0.end - range.0.start) .to_usize() .unwrap_or(usize::MAX), ) .saturating_add(1) }) } /// Returns the set of mapped chars, forgetting what they are mapped to. pub fn to_range_set(&self) -> RangeSet { RangeSet::from_sorted_vec(self.elts.iter().map(|x| (x.0, ())).collect()) } /// Modifies the values in place. pub fn map_values(&mut self, mut f: F) where F: FnMut(&V) -> V, { for &mut (_, ref mut data) in &mut self.elts { *data = f(data); } // We need to re-normalize, because we might have mapped two adjacent ranges to the same // value. self.normalize(); } /// Modifies this map to contain only those mappings with values `v` satisfying `f(v)`. pub fn retain_values(&mut self, mut f: F) where F: FnMut(&V) -> bool, { self.elts.retain(|x| f(&x.1)); } /// Returns a mutable view into this map. /// /// The ranges should not be modified, since that might violate our invariants. /// /// This method will eventually be removed, probably once anonymous return values allow is to /// write a values_mut() iterator more easily. pub fn as_mut_slice(&mut self) -> &mut [(Range, V)] { &mut self.elts } } #[derive(Copy, Clone, Debug)] pub struct PairIter<'a, T: 'a, V: 'a> { map: &'a RangeMap, next_range_idx: Option, next_key: T, } impl<'a, T: PrimInt, V> Iterator for PairIter<'a, T, V> { type Item = (T, &'a V); fn next(&mut self) -> Option { if let Some(idx) = self.next_range_idx { let ret = (self.next_key, &self.map.elts[idx].1); if self.next_key < self.map.elts[idx].0.end { self.next_key = self.next_key + T::one(); } else if idx < self.map.elts.len() - 1 { self.next_range_idx = Some(idx + 1); self.next_key = self.map.elts[idx + 1].0.start; } else { self.next_range_idx = None; } Some(ret) } else { None } } } /// A set of integers, implemented as a sorted list of (inclusive) ranges. #[derive(Clone, Eq, Hash, PartialEq)] pub struct RangeSet { map: RangeMap, } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct RangeIter<'a, T: PrimInt + 'a> { set: &'a RangeSet, next_idx: usize, } impl<'a, T: Debug + PrimInt> Iterator for RangeIter<'a, T> { type Item = Range; fn next(&mut self) -> Option> { if self.next_idx < self.set.num_ranges() { let ret = Some(self.set.map.elts[self.next_idx].0); self.next_idx += 1; ret } else { None } } } #[derive(Copy, Clone, Debug)] pub struct EltIter<'a, T: 'a + PrimInt> { set: &'a RangeSet, next_range_idx: Option, next_elt: T, } impl<'a, T: Debug + PrimInt> Iterator for EltIter<'a, T> { type Item = T; fn next(&mut self) -> Option { if let Some(idx) = self.next_range_idx { let ret = Some(self.next_elt); if self.next_elt >= self.set.map.elts[idx].0.end { if idx + 1 < self.set.num_ranges() { self.next_range_idx = Some(idx + 1); self.next_elt = self.set.map.elts[idx + 1].0.start; } else { self.next_range_idx = None; } } else { self.next_elt = self.next_elt + T::one(); } ret } else { None } } } impl Debug for RangeSet { // When alternate formatting is specified, only prints out the first buch of mappings. fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { try!(f.write_fmt(format_args!("RangeSet ("))); if f.alternate() { try!(f .debug_set() .entries(self.ranges().take(DISPLAY_LIMIT)) .finish()); if self.num_ranges() > DISPLAY_LIMIT { try!(f.write_str("...")); } } else { try!(f.debug_set().entries(self.ranges()).finish()); } try!(f.write_str(")")); Ok(()) } } impl FromIterator> for RangeSet { /// Builds a `RangeSet` from an iterator over `Range`s. fn from_iter>>(iter: I) -> Self { RangeSet { // The unwrap here is ok because RangeMap::try_from_iter only fails when two // overlapping ranges map to different values. Since every range here maps to the same // value, (i.e. ()), this will never happen. map: RangeMap::try_from_iter(iter.into_iter().map(|x| (x, ()))) .ok() .unwrap(), } } } impl RangeSet { /// Creates a new empty `RangeSet`. pub fn new() -> RangeSet { RangeSet { map: RangeMap::new(), } } /// Tests if this set is empty. pub fn is_empty(&self) -> bool { self.map.is_empty() } /// Tests whether this set contains every valid value of `T`. pub fn is_full(&self) -> bool { // We are assuming normalization here. self.num_ranges() == 1 && self.map.elts[0].0 == Range::full() } /// Returns the number of ranges used to represent this set. pub fn num_ranges(&self) -> usize { self.map.num_ranges() } /// Returns the number of elements in the set. /// /// This saturates at `usize::MAX`. pub fn num_elements(&self) -> usize { self.map.num_keys() } /// Returns an iterator over all ranges in this set. pub fn ranges<'a>(&'a self) -> RangeIter<'a, T> { RangeIter { set: self, next_idx: 0, } } /// Returns an iterator over all elements in this set. pub fn elements<'a>(&'a self) -> EltIter<'a, T> { if self.map.elts.is_empty() { EltIter { set: self, next_range_idx: None, next_elt: T::min_value(), } } else { EltIter { set: self, next_range_idx: Some(0), next_elt: self.map.elts[0].0.start, } } } /// Checks if this set contains a value. pub fn contains(&self, val: T) -> bool { self.map.get(val).is_some() } // Creates a RangeSet from a vector. The vector must be sorted, but it does not need to be // normalized. fn from_sorted_vec(vec: Vec<(Range, ())>) -> RangeSet { RangeSet { map: RangeMap::from_sorted_vec(vec), } } // Creates a RangeSet from a vector. The vector must be normalized, in the sense that it should // contain no adjacent ranges. fn from_norm_vec(vec: Vec<(Range, ())>) -> RangeSet { RangeSet { map: RangeMap::from_norm_vec(vec), } } /// Returns the union between `self` and `other`. pub fn union(&self, other: &RangeSet) -> RangeSet { if self.is_empty() { return other.clone(); } else if other.is_empty() { return self.clone(); } let mut ret = Vec::with_capacity(self.map.elts.len() + other.map.elts.len()); let mut it1 = self.map.elts.iter(); let mut it2 = other.map.elts.iter(); let mut r1 = it1.next(); let mut r2 = it2.next(); let mut cur_range: Option> = None; while r1.is_some() || r2.is_some() { let r1_start = if let Some(&(r, _)) = r1 { r.start } else { T::max_value() }; let r2_start = if let Some(&(r, _)) = r2 { r.start } else { T::max_value() }; if let Some(cur) = cur_range { if min(r1_start, r2_start) > cur.end.saturating_add(T::one()) { ret.push((cur_range.unwrap(), ())); cur_range = None; } } let cover = |cur: &mut Option>, next: &Range| { if let &mut Some(ref mut r) = cur { *r = r.cover(next); } else { *cur = Some(*next); } }; if r1_start < r2_start || r2.is_none() { cover(&mut cur_range, &r1.unwrap().0); r1 = it1.next(); } else { cover(&mut cur_range, &r2.unwrap().0); r2 = it2.next(); } } if cur_range.is_some() { ret.push((cur_range.unwrap(), ())); } RangeSet::from_norm_vec(ret) } /// Creates a set that contains every value of `T`. pub fn full() -> RangeSet { RangeSet::from_norm_vec(vec![(Range::full(), ())]) } /// Creates a set containing a single element. pub fn single(x: T) -> RangeSet { RangeSet::from_norm_vec(vec![(Range::single(x), ())]) } /// Creates a set containing all elements except the given ones. The input iterator must be /// sorted. If it is not, this will return `None`. pub fn except>(it: I) -> Option> { let mut ret = Vec::new(); let mut next_allowed = T::min_value(); let mut last_forbidden = T::max_value(); for i in it { if i > next_allowed { ret.push((Range::new(next_allowed, i - T::one()), ())); } else if i < next_allowed.saturating_sub(T::one()) { return None; } last_forbidden = i; next_allowed = i.saturating_add(T::one()); } if last_forbidden < T::max_value() { ret.push((Range::new(last_forbidden + T::one(), T::max_value()), ())); } Some(RangeSet::from_norm_vec(ret)) } /// Finds the intersection between this set and `other`. pub fn intersection(&self, other: &RangeSet) -> RangeSet { RangeSet { map: self.map.intersection(other), } } /// Returns the set of all characters that are not in this set. pub fn negated(&self) -> RangeSet { let mut ret = Vec::with_capacity(self.num_ranges() + 1); let mut last_end = T::min_value(); for range in self.ranges() { if range.start > last_end { ret.push((Range::new(last_end, range.start - T::one()), ())); } last_end = range.end.saturating_add(T::one()); } if last_end < T::max_value() { ret.push((Range::new(last_end, T::max_value()), ())); } RangeSet::from_norm_vec(ret) } } /// A multi-valued mapping from primitive integers to other data. #[derive(Clone, Eq, Hash, PartialEq)] pub struct RangeMultiMap { elts: Vec<(Range, V)>, } impl FromIterator<(Range, V)> for RangeMultiMap { /// Builds a `RangeMultiMap` from an iterator over `Range` and values.. fn from_iter, V)>>(iter: I) -> Self { RangeMultiMap::from_vec(iter.into_iter().collect()) } } impl Debug for RangeMultiMap { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { try!(f.write_fmt(format_args!("RangeMultiMap ("))); if f.alternate() { try!(f .debug_map() .entries( self.ranges_values() .map(|x| (&x.0, &x.1)) .take(DISPLAY_LIMIT) ) .finish()); if self.num_ranges() > DISPLAY_LIMIT { try!(f.write_str("...")); } } else { try!(f .debug_set() .entries(self.ranges_values().map(|x| (&x.0, &x.1))) .finish()); } try!(f.write_str(")")); Ok(()) } } impl RangeMultiMap { /// Creates a new empty map. pub fn new() -> RangeMultiMap { RangeMultiMap { elts: Vec::new() } } /// Returns the number of mapped ranges. pub fn num_ranges(&self) -> usize { self.elts.len() } /// Checks if the map is empty. pub fn is_empty(&self) -> bool { self.elts.is_empty() } /// Adds a new mapping from a range of characters to `value`. pub fn insert(&mut self, range: Range, value: V) { self.elts.push((range, value)); } /// Creates a map from a vector of pairs. pub fn from_vec(vec: Vec<(Range, V)>) -> RangeMultiMap { RangeMultiMap { elts: vec } } /// Returns a new `RangeMultiMap` containing only the mappings for keys that belong to the /// given set. pub fn intersection(&self, other: &RangeSet) -> RangeMultiMap { let mut ret = Vec::new(); for &(ref my_range, ref data) in &self.elts { let start_idx = other .map .elts .binary_search_by(|r| r.0.end.cmp(&my_range.start)) .unwrap_or_else(|x| x); for &(ref other_range, _) in &other.map.elts[start_idx..] { if my_range.start > other_range.end { break; } else if let Some(r) = my_range.intersection(other_range) { ret.push((r, data.clone())); } } } RangeMultiMap::from_vec(ret) } pub fn map_values(&mut self, mut f: F) where F: FnMut(&V) -> V, { for i in 0..self.elts.len() { self.elts[i].1 = f(&self.elts[i].1); } } /// Modifies this map in place to only contain mappings whose values `v` satisfy `f(v)`. pub fn retain_values(&mut self, mut f: F) where F: FnMut(&V) -> bool, { self.elts.retain(|x| f(&x.1)); } /// Returns the underlying `Vec`. pub fn into_vec(self) -> Vec<(Range, V)> { self.elts } /// Iterates over all the mapped ranges and values. pub fn ranges_values<'a>(&'a self) -> std::slice::Iter<'a, (Range, V)> { self.elts.iter() } } impl RangeMultiMap { /// Makes the ranges sorted and non-overlapping. The data associated with each range will /// be a `Vec` instead of a single `T`. pub fn group(&self) -> RangeMap> { if self.elts.is_empty() { return RangeMap::new(); } let mut start_chars = Vec::with_capacity(self.elts.len() * 2); for &(ref range, _) in self.elts.iter() { start_chars.push(range.start); if range.end < T::max_value() { start_chars.push(range.end + T::one()); } } start_chars.sort(); start_chars.dedup(); let mut ret: Vec<(Range, Vec)> = Vec::with_capacity(start_chars.len()); for pair in start_chars.windows(2) { ret.push((Range::new(pair[0], pair[1] - T::one()), Vec::new())); } ret.push(( Range::new(*start_chars.last().unwrap(), T::max_value()), Vec::new(), )); for &(range, ref val) in self.elts.iter() { // The unwrap is OK because start_chars contains range.start for every range in elts. let mut idx = start_chars.binary_search(&range.start).unwrap(); while idx < start_chars.len() && start_chars[idx] <= range.end { ret[idx].1.push(val.clone()); idx += 1; } } ret.retain(|x| !x.1.is_empty()); RangeMap::from_sorted_vec(ret) } } #[cfg(test)] mod tests { use super::*; use num_iter::range_inclusive; use num_traits::PrimInt; use quickcheck::{quickcheck, Arbitrary, Gen, TestResult}; use std::cmp::{max, min}; use std::fmt::Debug; use std::i32; use std::ops::Add; impl Arbitrary for Range { fn arbitrary(g: &mut G) -> Self { let a = T::arbitrary(g); let b = T::arbitrary(g); Range::new(min(a, b), max(a, b)) } } impl Arbitrary for RangeMultiMap where T: Arbitrary + Debug + PrimInt, { fn arbitrary(g: &mut G) -> Self { RangeMultiMap::from_vec(Vec::arbitrary(g)) } fn shrink(&self) -> Box> { Box::new(self.elts.shrink().map(|v| RangeMultiMap::from_vec(v))) } } impl Arbitrary for RangeMap where T: Arbitrary + Debug + PrimInt, { fn arbitrary(g: &mut G) -> Self { let map: RangeMap> = RangeMultiMap::arbitrary(g).group(); // TODO: replace fold with sum once it's stable map.ranges_values() .map(|x| (x.0, x.1.iter().fold(0, Add::add))) .collect() } fn shrink(&self) -> Box> { Box::new(self.elts.shrink().map(|v| RangeMap::from_norm_vec(v))) } } impl Arbitrary for RangeSet { fn arbitrary(g: &mut G) -> Self { RangeMap::arbitrary(g).to_range_set() } fn shrink(&self) -> Box> { Box::new(self.map.elts.shrink().map(|v| RangeSet::from_norm_vec(v))) } } #[test] fn range_intersects_intersection() { fn prop(r1: Range, r2: Range) -> bool { r1.intersection(&r2).is_some() == r1.intersects(&r2) } quickcheck(prop as fn(_, _) -> _); } #[test] fn range_intersection_contains() { fn prop(r1: Range, r2: Range, x: i32) -> TestResult { if let Some(r) = r1.intersection(&r2) { TestResult::from_bool(r.contains(x) == (r1.contains(x) && r2.contains(x))) } else { TestResult::discard() } } quickcheck(prop as fn(_, _, _) -> _); } #[test] #[should_panic] fn range_backwards() { map(vec![(5, 1, 1), (6, 10, 2)]); } #[test] fn range_intersection_cover() { fn prop(r1: Range, r2: Range) -> bool { r1 == r1.cover(&r2).intersection(&r1).unwrap() } quickcheck(prop as fn(_, _) -> _); } fn map(vec: Vec<(i32, i32, i32)>) -> RangeMap { vec.into_iter() .map(|(a, b, c)| (Range::new(a, b), c)) .collect() } #[test] fn rangemap_overlapping() { assert_eq!(map(vec![(1, 5, 1), (2, 10, 1)]), map(vec![(1, 10, 1)])); assert_eq!( map(vec![(1, 5, 1), (2, 10, 1), (9, 11, 1)]), map(vec![(1, 11, 1)]) ); map(vec![(1, 5, 1), (6, 10, 2)]); } #[test] #[should_panic] fn rangemap_overlapping_nonequal() { map(vec![(1, 5, 1), (5, 10, 2)]); } #[test] fn rangemap_intersection() { fn prop(map: RangeMap, set: RangeSet) -> bool { let int = map.intersection(&set); set.elements().all(|x| map.get(x) == int.get(x)) && int.keys_values().all(|x| set.contains(x.0)) } quickcheck(prop as fn(_, _) -> _); } #[test] fn rangemap_num_ranges() { fn prop(map: RangeMap) -> bool { map.num_ranges() == map.ranges_values().count() } quickcheck(prop as fn(_) -> _); } #[test] fn rangemap_num_keys() { fn prop(map: RangeMap) -> bool { map.num_keys() == map.keys_values().count() } quickcheck(prop as fn(_) -> _); } #[test] fn rangemap_map_values() { fn prop(map: RangeMap, x: i32) -> bool { let f = |y: &i32| (x + *y) % 10; let new_map = { let mut new_map = map.clone(); new_map.map_values(&f); new_map }; let new_map_norm = { let mut new_map_norm = new_map.clone(); new_map_norm.normalize(); new_map_norm }; new_map .keys_values() .all(|(k, v)| f(map.get(k).unwrap()) == *v) && map .keys_values() .all(|(k, v)| *new_map.get(k).unwrap() == f(v)) && new_map == new_map_norm } quickcheck(prop as fn(_, _) -> _); } #[test] fn rangemap_retain_values() { fn prop(map: RangeMap, r: Range) -> bool { let mut new_map = map.clone(); new_map.retain_values(|v| r.contains(*v)); new_map.keys_values().all(|(_, v)| r.contains(*v)) && map .keys_values() .all(|(k, v)| !r.contains(*v) || new_map.get(k).unwrap() == v) } quickcheck(prop as fn(_, _) -> _); } #[test] fn rangeset_contains() { fn prop(set: RangeSet) -> bool { set.elements().all(|e| set.contains(e)) } quickcheck(prop as fn(_) -> _); } #[test] fn rangeset_num_ranges() { fn prop(set: RangeSet) -> bool { set.num_ranges() == set.ranges().count() } quickcheck(prop as fn(_) -> _); } #[test] fn rangeset_num_elements() { fn prop(set: RangeSet) -> bool { set.num_elements() == set.elements().count() } quickcheck(prop as fn(_) -> _); } #[test] fn rangeset_union() { fn prop(s1: RangeSet, s2: RangeSet) -> bool { let un = s1.union(&s2); un.elements().all(|e| s1.contains(e) || s2.contains(e)) && s1.elements().all(|e| un.contains(e)) && s2.elements().all(|e| un.contains(e)) } quickcheck(prop as fn(_, _) -> _); } #[test] fn rangeset_intersection() { fn prop(s1: RangeSet, s2: RangeSet) -> bool { let int = s1.intersection(&s2); int.elements().all(|e| s1.contains(e) && s2.contains(e)) && s1.elements().all(|e| int.contains(e) == s2.contains(e)) } quickcheck(prop as fn(_, _) -> _); } #[test] fn rangeset_negate() { fn prop(set: RangeSet) -> bool { let neg = set.negated(); neg.elements().all(|e| !set.contains(e)) && set.elements().all(|e| !neg.contains(e)) && neg.negated() == set } quickcheck(prop as fn(_) -> _); } #[test] fn rangeset_except() { fn prop(mut except: Vec) -> bool { except.sort(); let set = RangeSet::except(except.iter().cloned()).unwrap(); set.elements().all(|e| except.binary_search(&e).is_err()) && except.iter().all(|&e| !set.contains(e)) } quickcheck(prop as fn(_) -> _); } #[test] fn rangeset_except_unsorted() { assert_eq!(None, RangeSet::except([1i32, 3, 2].iter().cloned())); } // Check that things don't panic when we have MIN and MAX in the ranges (quickcheck doesn't // check this properly). #[test] fn rangemultimap_boundaries() { assert_eq!( RangeMultiMap::from_vec(vec![ (Range::new(i32::MIN, 200), 5), (Range::new(100, i32::MAX), 10), ]) .group(), RangeMap::from_sorted_vec(vec![ (Range::new(i32::MIN, 99), vec![5]), (Range::new(100, 200), vec![5, 10]), (Range::new(201, i32::MAX), vec![10]), ]) ); } #[test] fn rangemultimap_group() { fn prop(mm_vec: Vec<(Range, i32)>) -> bool { let mm = RangeMultiMap::from_vec(mm_vec.clone()); let grouped = mm.group(); mm_vec.into_iter().all(|(range, val)| { range_inclusive(range.start, range.end) .all(|i| grouped.get(i).unwrap().contains(&val)) }) } quickcheck(prop as fn(_) -> _); } }