use super::range_wrapper::RangeInclusiveStartWrapper; use crate::range_wrapper::RangeInclusiveEndWrapper; use crate::std_ext::*; use alloc::collections::BTreeMap; use core::borrow::Borrow; use core::cmp::Ordering; use core::fmt::{self, Debug}; use core::hash::Hash; use core::iter::{DoubleEndedIterator, FromIterator}; use core::marker::PhantomData; use core::ops::{RangeFrom, RangeInclusive}; use core::prelude::v1::*; #[cfg(feature = "serde1")] use serde::{ de::{Deserialize, Deserializer, SeqAccess, Visitor}, ser::{Serialize, Serializer}, }; /// A map whose keys are stored as ranges bounded /// inclusively below and above `(start..=end)`. /// /// Contiguous and overlapping ranges that map to the same value /// are coalesced into a single range. /// /// Successor and predecessor functions must be provided for /// the key type `K`, so that we can detect adjacent but non-overlapping /// (closed) ranges. (This is not a problem for half-open ranges, /// because adjacent ranges can be detected using equality of range ends alone.) /// /// You can provide these functions either by implementing the /// [`StepLite`] trait for your key type `K`, or, /// if this is impossible because of Rust's "orphan rules", /// you can provide equivalent free functions using the `StepFnsT` type parameter. /// [`StepLite`] is implemented for all standard integer types, /// but not for any third party crate types. #[derive(Clone)] pub struct RangeInclusiveMap { // Wrap ranges so that they are `Ord`. // See `range_wrapper.rs` for explanation. pub(crate) btm: BTreeMap, V>, _phantom: PhantomData, } impl Default for RangeInclusiveMap { fn default() -> Self { Self { btm: BTreeMap::default(), _phantom: PhantomData, } } } impl Hash for RangeInclusiveMap where K: Hash, V: Hash, { fn hash(&self, state: &mut H) { state.write_usize(self.btm.len()); for elt in self.iter() { elt.hash(state); } } } impl PartialEq for RangeInclusiveMap where K: PartialEq, V: PartialEq, { fn eq(&self, other: &RangeInclusiveMap) -> bool { self.btm == other.btm } } impl Eq for RangeInclusiveMap where K: Eq, V: Eq, { } impl PartialOrd for RangeInclusiveMap where K: PartialOrd, V: PartialOrd, { #[inline] fn partial_cmp(&self, other: &RangeInclusiveMap) -> Option { self.btm.partial_cmp(&other.btm) } } impl Ord for RangeInclusiveMap where K: Ord, V: Ord, { #[inline] fn cmp(&self, other: &RangeInclusiveMap) -> Ordering { self.btm.cmp(&other.btm) } } #[cfg(feature = "quickcheck")] impl quickcheck::Arbitrary for RangeInclusiveMap where K: quickcheck::Arbitrary + Ord + StepLite, V: quickcheck::Arbitrary + Eq, { fn arbitrary(g: &mut quickcheck::Gen) -> Self { // REVISIT: allocation could be avoided if Gen::gen_size were public (https://github.com/BurntSushi/quickcheck/issues/326#issue-2653601170) , _)>>::arbitrary(g) .into_iter() .filter(|(range, _)| !range.is_empty()) .collect() } } impl RangeInclusiveMap { /// Gets an iterator over all pairs of key range and value, /// ordered by key range. /// /// The iterator element type is `(&'a RangeInclusive, &'a V)`. pub fn iter(&self) -> Iter<'_, K, V> { Iter { inner: self.btm.iter(), } } } impl RangeInclusiveMap where K: Ord + Clone + StepLite, V: Eq + Clone, { /// Makes a new empty `RangeInclusiveMap`. #[cfg(feature = "const_fn")] pub const fn new() -> Self { Self::new_with_step_fns() } /// Makes a new empty `RangeInclusiveMap`. #[cfg(not(feature = "const_fn"))] pub fn new() -> Self { Self::new_with_step_fns() } } impl RangeInclusiveMap where K: Ord + Clone, V: Eq + Clone, StepFnsT: StepFns, { /// Makes a new empty `RangeInclusiveMap`, specifying successor and /// predecessor functions defined separately from `K` itself. /// /// This is useful as a workaround for Rust's "orphan rules", /// which prevent you from implementing `StepLite` for `K` if `K` /// is a foreign type. /// /// **NOTE:** This will likely be deprecated and then eventually /// removed once the standard library's [Step](core::iter::Step) /// trait is stabilised, as most crates will then likely implement [Step](core::iter::Step) /// for their types where appropriate. /// /// See [this issue](https://github.com/rust-lang/rust/issues/42168) /// for details about that stabilization process. #[cfg(not(feature = "const_fn"))] pub fn new_with_step_fns() -> Self { Self { btm: BTreeMap::new(), _phantom: PhantomData, } } #[cfg(feature = "const_fn")] pub const fn new_with_step_fns() -> Self { Self { btm: BTreeMap::new(), _phantom: PhantomData, } } /// Returns a reference to the value corresponding to the given key, /// if the key is covered by any range in the map. pub fn get(&self, key: &K) -> Option<&V> { self.get_key_value(key).map(|(_range, value)| value) } /// Returns the range-value pair (as a pair of references) corresponding /// to the given key, if the key is covered by any range in the map. pub fn get_key_value(&self, key: &K) -> Option<(&RangeInclusive, &V)> { use core::ops::Bound; // The only stored range that could contain the given key is the // last stored range whose start is less than or equal to this key. let key_as_start = RangeInclusiveStartWrapper::new(key.clone()..=key.clone()); self.btm .range((Bound::Unbounded, Bound::Included(key_as_start))) .next_back() .filter(|(range_start_wrapper, _value)| { // Does the only candidate range contain // the requested key? range_start_wrapper.contains(key) }) .map(|(range_start_wrapper, value)| (&range_start_wrapper.range, value)) } /// Returns `true` if any range in the map covers the specified key. pub fn contains_key(&self, key: &K) -> bool { self.get(key).is_some() } /// Clears the map, removing all elements. pub fn clear(&mut self) { self.btm.clear(); } /// Returns the number of elements in the map. pub fn len(&self) -> usize { self.btm.len() } /// Returns true if the map contains no elements. pub fn is_empty(&self) -> bool { self.btm.is_empty() } /// Insert a pair of key range and value into the map. /// /// If the inserted range partially or completely overlaps any /// existing range in the map, then the existing range (or ranges) will be /// partially or completely replaced by the inserted range. /// /// If the inserted range either overlaps or is immediately adjacent /// any existing range _mapping to the same value_, then the ranges /// will be coalesced into a single contiguous range. /// /// # Panics /// /// Panics if range `start > end`. pub fn insert(&mut self, range: RangeInclusive, value: V) { use core::ops::Bound; // Backwards ranges don't make sense. // `RangeInclusive` doesn't enforce this, // and we don't want weird explosions further down // if someone gives us such a range. assert!( range.start() <= range.end(), "Range start can not be after range end" ); // Wrap up the given range so that we can "borrow" // it as a wrapper reference to either its start or end. // See `range_wrapper.rs` for explanation of these hacks. let mut new_range_start_wrapper: RangeInclusiveStartWrapper = RangeInclusiveStartWrapper::new(range); let new_value = value; // Is there a stored range either overlapping the start of // the range to insert or immediately preceding it? // // If there is any such stored range, it will be the last // whose start is less than or equal to _one less than_ // the start of the range to insert, or the one before that // if both of the above cases exist. let mut candidates = self .btm .range::, ( Bound<&RangeInclusiveStartWrapper>, Bound<&RangeInclusiveStartWrapper>, )>((Bound::Unbounded, Bound::Included(&new_range_start_wrapper))) .rev() .take(2) .filter(|(stored_range_start_wrapper, _stored_value)| { // Does the candidate range either overlap // or immediately precede the range to insert? // (Remember that it might actually cover the _whole_ // range to insert and then some.) stored_range_start_wrapper .touches::(&new_range_start_wrapper.end_wrapper.range) }); if let Some(mut candidate) = candidates.next() { // Or the one before it if both cases described above exist. if let Some(another_candidate) = candidates.next() { candidate = another_candidate; } let (stored_range_start_wrapper, stored_value) = (candidate.0.clone(), candidate.1.clone()); self.adjust_touching_ranges_for_insert( stored_range_start_wrapper, stored_value, &mut new_range_start_wrapper.end_wrapper.range, &new_value, ); } // Are there any stored ranges whose heads overlap or immediately // follow the range to insert? // // If there are any such stored ranges (that weren't already caught above), // their starts will fall somewhere after the start of the range to insert, // and on, before, or _immediately after_ its end. To handle that last case // without risking arithmetic overflow, we'll consider _one more_ stored item past // the end of the end of the range to insert. // // REVISIT: Possible micro-optimisation: `impl Borrow for RangeInclusiveStartWrapper` // and use that to search here, to avoid constructing another `RangeInclusiveStartWrapper`. let second_last_possible_start = new_range_start_wrapper.end().clone(); let second_last_possible_start = RangeInclusiveStartWrapper::new( second_last_possible_start.clone()..=second_last_possible_start, ); while let Some((stored_range_start_wrapper, stored_value)) = self .btm .range::, ( Bound<&RangeInclusiveStartWrapper>, Bound<&RangeInclusiveStartWrapper>, )>(( Bound::Included(&new_range_start_wrapper), // We would use something like `Bound::Included(&last_possible_start)`, // but making `last_possible_start` might cause arithmetic overflow; // instead decide inside the loop whether we've gone too far and break. Bound::Unbounded, )) .next() { // A couple of extra exceptions are needed at the // end of the subset of stored ranges we want to consider, // in part because we use `Bound::Unbounded` above. // (See comments up there, and in the individual cases below.) let stored_start = stored_range_start_wrapper.start(); if *stored_start > *second_last_possible_start.start() { let latest_possible_start = StepFnsT::add_one(second_last_possible_start.start()); if *stored_start > latest_possible_start { // We're beyond the last stored range that could be relevant. // Avoid wasting time on irrelevant ranges, or even worse, looping forever. // (`adjust_touching_ranges_for_insert` below assumes that the given range // is relevant, and behaves very poorly if it is handed a range that it // shouldn't be touching.) break; } if *stored_start == latest_possible_start && *stored_value != new_value { // We are looking at the last stored range that could be relevant, // but it has a different value, so we don't want to merge with it. // We must explicitly break here as well, because `adjust_touching_ranges_for_insert` // below assumes that the given range is relevant, and behaves very poorly if it // is handed a range that it shouldn't be touching. break; } } let stored_range_start_wrapper = stored_range_start_wrapper.clone(); let stored_value = stored_value.clone(); self.adjust_touching_ranges_for_insert( stored_range_start_wrapper, stored_value, &mut new_range_start_wrapper.end_wrapper.range, &new_value, ); } // Insert the (possibly expanded) new range, and we're done! self.btm.insert(new_range_start_wrapper, new_value); } /// Removes a range from the map, if all or any of it was present. /// /// If the range to be removed _partially_ overlaps any ranges /// in the map, then those ranges will be contracted to no /// longer cover the removed range. /// /// /// # Panics /// /// Panics if range `start > end`. pub fn remove(&mut self, range: RangeInclusive) { use core::ops::Bound; // Backwards ranges don't make sense. // `RangeInclusive` doesn't enforce this, // and we don't want weird explosions further down // if someone gives us such a range. assert!( range.start() <= range.end(), "Range start can not be after range end" ); let range_start_wrapper: RangeInclusiveStartWrapper = RangeInclusiveStartWrapper::new(range); let range = &range_start_wrapper.range; // Is there a stored range overlapping the start of // the range to insert? // // If there is any such stored range, it will be the last // whose start is less than or equal to the start of the range to insert. if let Some((stored_range_start_wrapper, stored_value)) = self .btm .range::, ( Bound<&RangeInclusiveStartWrapper>, Bound<&RangeInclusiveStartWrapper>, )>((Bound::Unbounded, Bound::Included(&range_start_wrapper))) .next_back() .filter(|(stored_range_start_wrapper, _stored_value)| { // Does the only candidate range overlap // the range to insert? stored_range_start_wrapper.overlaps(range) }) .map(|(stored_range_start_wrapper, stored_value)| { (stored_range_start_wrapper.clone(), stored_value.clone()) }) { self.adjust_overlapping_ranges_for_remove( stored_range_start_wrapper, stored_value, range, ); } // Are there any stored ranges whose heads overlap the range to insert? // // If there are any such stored ranges (that weren't already caught above), // their starts will fall somewhere after the start of the range to insert, // and on or before its end. // // REVISIT: Possible micro-optimisation: `impl Borrow for RangeInclusiveStartWrapper` // and use that to search here, to avoid constructing another `RangeInclusiveStartWrapper`. let new_range_end_as_start = RangeInclusiveStartWrapper::new(range.end().clone()..=range.end().clone()); while let Some((stored_range_start_wrapper, stored_value)) = self .btm .range::, ( Bound<&RangeInclusiveStartWrapper>, Bound<&RangeInclusiveStartWrapper>, )>(( Bound::Excluded(&range_start_wrapper), Bound::Included(&new_range_end_as_start), )) .next() .map(|(stored_range_start_wrapper, stored_value)| { (stored_range_start_wrapper.clone(), stored_value.clone()) }) { self.adjust_overlapping_ranges_for_remove( stored_range_start_wrapper, stored_value, range, ); } } fn adjust_touching_ranges_for_insert( &mut self, stored_range_start_wrapper: RangeInclusiveStartWrapper, stored_value: V, new_range: &mut RangeInclusive, new_value: &V, ) { use core::cmp::{max, min}; if stored_value == *new_value { // The ranges have the same value, so we can "adopt" // the stored range. // // This means that no matter how big or where the stored range is, // we will expand the new range's bounds to subsume it, // and then delete the stored range. let new_start = min(new_range.start(), stored_range_start_wrapper.start()).clone(); let new_end = max(new_range.end(), stored_range_start_wrapper.end()).clone(); *new_range = new_start..=new_end; self.btm.remove(&stored_range_start_wrapper); } else { // The ranges have different values. if new_range.overlaps(&stored_range_start_wrapper.range) { // The ranges overlap. This is a little bit more complicated. // Delete the stored range, and then add back between // 0 and 2 subranges at the ends of the range to insert. self.btm.remove(&stored_range_start_wrapper); if stored_range_start_wrapper.start() < new_range.start() { // Insert the piece left of the range to insert. self.btm.insert( RangeInclusiveStartWrapper::new( stored_range_start_wrapper.start().clone() ..=StepFnsT::sub_one(new_range.start()), ), stored_value.clone(), ); } if stored_range_start_wrapper.end() > new_range.end() { // Insert the piece right of the range to insert. self.btm.insert( RangeInclusiveStartWrapper::new( StepFnsT::add_one(new_range.end()) ..=stored_range_start_wrapper.end().clone(), ), stored_value, ); } } else { // No-op; they're not overlapping, // so we can just keep both ranges as they are. } } } fn adjust_overlapping_ranges_for_remove( &mut self, stored_range_start_wrapper: RangeInclusiveStartWrapper, stored_value: V, range_to_remove: &RangeInclusive, ) { // Delete the stored range, and then add back between // 0 and 2 subranges at the ends of the range to insert. self.btm.remove(&stored_range_start_wrapper); let stored_range = stored_range_start_wrapper.end_wrapper.range; if stored_range.start() < range_to_remove.start() { // Insert the piece left of the range to insert. self.btm.insert( RangeInclusiveStartWrapper::new( stored_range.start().clone()..=StepFnsT::sub_one(range_to_remove.start()), ), stored_value.clone(), ); } if stored_range.end() > range_to_remove.end() { // Insert the piece right of the range to insert. self.btm.insert( RangeInclusiveStartWrapper::new( StepFnsT::add_one(range_to_remove.end())..=stored_range.end().clone(), ), stored_value, ); } } /// Gets an iterator over all the maximally-sized ranges /// contained in `outer_range` that are not covered by /// any range stored in the map. /// /// The iterator element type is `RangeInclusive`. pub fn gaps<'a>(&'a self, outer_range: &'a RangeInclusive) -> Gaps<'a, K, V, StepFnsT> { let overlap_iter = self.overlapping(outer_range); Gaps { candidate_needs_plus_one: false, candidate_start: outer_range.start(), query_end: outer_range.end(), btm_range_iter: overlap_iter.btm_range_iter, // We'll start the candidate range at the start of the outer range // without checking what's there. Each time we yield an item, // we'll skip any ranges we find before the next gap. _phantom: PhantomData, } } /// Gets an iterator over all the stored ranges that are /// either partially or completely overlapped by the given range. pub fn overlapping>>(&self, range: R) -> Overlapping { // Find the first matching stored range by its _end_, // using sneaky layering and `Borrow` implementation. (See `range_wrappers` module.) let start_sliver = RangeInclusiveEndWrapper::new( range.borrow().start().clone()..=range.borrow().start().clone(), ); let btm_range_iter = self .btm .range::, RangeFrom<&RangeInclusiveEndWrapper>>( &start_sliver.., ); Overlapping { query_range: range, btm_range_iter, } } /// Returns `true` if any range in the map completely or partially /// overlaps the given range. pub fn overlaps(&self, range: &RangeInclusive) -> bool { self.overlapping(range).next().is_some() } /// Returns the first range-value pair in this map, if one exists. The range in this pair is the /// minimum range in the map. pub fn first_range_value(&self) -> Option<(&RangeInclusive, &V)> { self.btm .first_key_value() .map(|(range, value)| (&range.end_wrapper.range, value)) } /// Returns the last range-value pair in this map, if one exists. The range in this pair is the /// maximum range in the map. pub fn last_range_value(&self) -> Option<(&RangeInclusive, &V)> { self.btm .last_key_value() .map(|(range, value)| (&range.end_wrapper.range, value)) } } /// An iterator over the entries of a `RangeInclusiveMap`, ordered by key range. /// /// The iterator element type is `(&'a RangeInclusive, &'a V)`. /// /// This `struct` is created by the [`iter`] method on [`RangeInclusiveMap`]. See its /// documentation for more. /// /// [`iter`]: RangeInclusiveMap::iter pub struct Iter<'a, K, V> { inner: alloc::collections::btree_map::Iter<'a, RangeInclusiveStartWrapper, V>, } impl<'a, K, V> Iterator for Iter<'a, K, V> where K: 'a, V: 'a, { type Item = (&'a RangeInclusive, &'a V); fn next(&mut self) -> Option { self.inner.next().map(|(by_start, v)| (&by_start.range, v)) } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> where K: 'a, V: 'a, { fn next_back(&mut self) -> Option { self.inner .next_back() .map(|(range, value)| (&range.end_wrapper.range, value)) } } /// An owning iterator over the entries of a `RangeInclusiveMap`, ordered by key range. /// /// The iterator element type is `(RangeInclusive, V)`. /// /// This `struct` is created by the [`into_iter`] method on [`RangeInclusiveMap`] /// (provided by the `IntoIterator` trait). See its documentation for more. /// /// [`into_iter`]: IntoIterator::into_iter pub struct IntoIter { inner: alloc::collections::btree_map::IntoIter, V>, } impl IntoIterator for RangeInclusiveMap { type Item = (RangeInclusive, V); type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { IntoIter { inner: self.btm.into_iter(), } } } impl Iterator for IntoIter { type Item = (RangeInclusive, V); fn next(&mut self) -> Option<(RangeInclusive, V)> { self.inner .next() .map(|(by_start, v)| (by_start.end_wrapper.range, v)) } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } impl DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option { self.inner .next_back() .map(|(range, value)| (range.end_wrapper.range, value)) } } // We can't just derive this automatically, because that would // expose irrelevant (and private) implementation details. // Instead implement it in the same way that the underlying BTreeMap does. impl Debug for RangeInclusiveMap where K: Ord + Clone + StepLite, V: Eq + Clone, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_map().entries(self.iter()).finish() } } impl FromIterator<(RangeInclusive, V)> for RangeInclusiveMap where K: Ord + Clone + StepLite, V: Eq + Clone, { fn from_iter, V)>>(iter: T) -> Self { let mut range_map = RangeInclusiveMap::new(); range_map.extend(iter); range_map } } impl Extend<(RangeInclusive, V)> for RangeInclusiveMap where K: Ord + Clone + StepLite, V: Eq + Clone, { fn extend, V)>>(&mut self, iter: T) { iter.into_iter().for_each(move |(k, v)| { self.insert(k, v); }) } } #[cfg(feature = "serde1")] impl Serialize for RangeInclusiveMap where K: Ord + Clone + StepLite + Serialize, V: Eq + Clone + Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { use serde::ser::SerializeSeq; let mut seq = serializer.serialize_seq(Some(self.btm.len()))?; for (k, v) in self.iter() { seq.serialize_element(&((k.start(), k.end()), &v))?; } seq.end() } } #[cfg(feature = "serde1")] impl<'de, K, V> Deserialize<'de> for RangeInclusiveMap where K: Ord + Clone + StepLite + Deserialize<'de>, V: Eq + Clone + Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_seq(RangeInclusiveMapVisitor::new()) } } #[cfg(feature = "serde1")] struct RangeInclusiveMapVisitor { marker: PhantomData RangeInclusiveMap>, } #[cfg(feature = "serde1")] impl RangeInclusiveMapVisitor { fn new() -> Self { RangeInclusiveMapVisitor { marker: PhantomData, } } } #[cfg(feature = "serde1")] impl<'de, K, V> Visitor<'de> for RangeInclusiveMapVisitor where K: Ord + Clone + StepLite + Deserialize<'de>, V: Eq + Clone + Deserialize<'de>, { type Value = RangeInclusiveMap; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("RangeInclusiveMap") } fn visit_seq(self, mut access: A) -> Result where A: SeqAccess<'de>, { let mut range_inclusive_map = RangeInclusiveMap::new(); while let Some(((start, end), value)) = access.next_element()? { range_inclusive_map.insert(start..=end, value); } Ok(range_inclusive_map) } } /// An iterator over all ranges not covered by a `RangeInclusiveMap`. /// /// The iterator element type is `RangeInclusive`. /// /// This `struct` is created by the [`gaps`] method on [`RangeInclusiveMap`]. See its /// documentation for more. /// /// [`gaps`]: RangeInclusiveMap::gaps pub struct Gaps<'a, K, V, StepFnsT> { /// Would be redundant, but we need an extra flag to /// avoid overflowing when dealing with inclusive ranges. /// /// All other things here are ignored if `done` is `true`. candidate_needs_plus_one: bool, candidate_start: &'a K, query_end: &'a K, btm_range_iter: alloc::collections::btree_map::Range<'a, RangeInclusiveStartWrapper, V>, _phantom: PhantomData, } // `Gaps` is always fused. (See definition of `next` below.) impl<'a, K, V, StepFnsT> core::iter::FusedIterator for Gaps<'a, K, V, StepFnsT> where K: Ord + Clone, StepFnsT: StepFns, { } impl<'a, K, V, StepFnsT> Iterator for Gaps<'a, K, V, StepFnsT> where K: Ord + Clone, StepFnsT: StepFns, { type Item = RangeInclusive; fn next(&mut self) -> Option { for overlap in self.btm_range_iter.by_ref() { let overlap = overlap.0; // If the range in the map has advanced beyond the query range, return // any tail gap. if *self.query_end < *overlap.start() { break; } let candidate_needs_plus_one = core::mem::replace(&mut self.candidate_needs_plus_one, true); let cur_candidate_start = core::mem::replace(&mut self.candidate_start, overlap.end()); let cur_candidate_start = if candidate_needs_plus_one { StepFnsT::add_one(cur_candidate_start) } else { cur_candidate_start.clone() }; if cur_candidate_start < *overlap.start() { let gap = cur_candidate_start..=StepFnsT::sub_one(overlap.start()); return Some(gap); } } // Now that we've run out of items, the only other possible // gap is one at the end of the outer range. let candidate_needs_plus_one = core::mem::replace(&mut self.candidate_needs_plus_one, true); let cur_candidate_start = core::mem::replace(&mut self.candidate_start, self.query_end); if candidate_needs_plus_one { if *cur_candidate_start < *self.query_end { return Some(StepFnsT::add_one(cur_candidate_start)..=self.query_end.clone()); } } else if *cur_candidate_start <= *self.query_end { // There's a gap at the end! return Some(cur_candidate_start.clone()..=self.query_end.clone()); } None } } /// An iterator over all stored ranges partially or completely /// overlapped by a given range. /// /// The iterator element type is `(&'a RangeInclusive, &'a V)`. /// /// This `struct` is created by the [`overlapping`] method on [`RangeInclusiveMap`]. See its /// documentation for more. /// /// [`overlapping`]: RangeInclusiveMap::overlapping pub struct Overlapping<'a, K, V, R: Borrow> = &'a RangeInclusive> { query_range: R, btm_range_iter: alloc::collections::btree_map::Range<'a, RangeInclusiveStartWrapper, V>, } // `Overlapping` is always fused. (See definition of `next` below.) impl<'a, K, V, R: Borrow>> core::iter::FusedIterator for Overlapping<'a, K, V, R> where K: Ord + Clone { } impl<'a, K, V, R: Borrow>> Iterator for Overlapping<'a, K, V, R> where K: Ord + Clone, { type Item = (&'a RangeInclusive, &'a V); fn next(&mut self) -> Option { if let Some((k, v)) = self.btm_range_iter.next() { if k.start() <= self.query_range.borrow().end() { Some((&k.range, v)) } else { // The rest of the items in the underlying iterator // are past the query range. We can keep taking items // from that iterator and this will remain true, // so this is enough to make the iterator fused. None } } else { None } } } impl<'a, K, V, R: Borrow>> DoubleEndedIterator for Overlapping<'a, K, V, R> where K: Ord + Clone, { fn next_back(&mut self) -> Option { while let Some((k, v)) = self.btm_range_iter.next_back() { if k.start() <= self.query_range.borrow().end() { return Some((&k.range, v)); } } None } } impl From<[(RangeInclusive, V); N]> for RangeInclusiveMap { fn from(value: [(RangeInclusive, V); N]) -> Self { let mut map = Self::new(); for (range, value) in IntoIterator::into_iter(value) { map.insert(range, value); } map } } /// Create a [`RangeInclusiveMap`] from key-value pairs. /// /// # Example /// /// ```rust /// # use rangemap::range_inclusive_map; /// let map = range_inclusive_map!{ /// 0..=100 => "abc", /// 100..=200 => "def", /// 200..=300 => "ghi" /// }; /// ``` #[macro_export] macro_rules! range_inclusive_map { ($($k:expr => $v:expr),* $(,)?) => {{ $crate::RangeInclusiveMap::from([$(($k, $v)),*]) }}; } #[cfg(test)] mod tests { use super::*; use alloc as std; use alloc::{format, string::String, vec, vec::Vec}; use proptest::prelude::*; use test_strategy::proptest; impl Arbitrary for RangeInclusiveMap where K: Ord + Clone + Debug + StepLite + Arbitrary + 'static, V: Clone + Eq + Arbitrary + 'static, { type Parameters = (); type Strategy = BoxedStrategy; fn arbitrary_with(_parameters: Self::Parameters) -> Self::Strategy { any::, V)>>() .prop_map(|ranges| ranges.into_iter().collect::>()) .boxed() } } #[proptest] #[allow(clippy::len_zero)] fn test_len(mut map: RangeInclusiveMap) { assert_eq!(map.len(), map.iter().count()); assert_eq!(map.is_empty(), map.len() == 0); map.clear(); assert_eq!(map.len(), 0); assert!(map.is_empty()); assert_eq!(map.iter().count(), 0); } #[proptest] fn test_first(set: RangeInclusiveMap) { assert_eq!( set.first_range_value(), set.iter().min_by_key(|(range, _)| range.start()) ); } #[proptest] fn test_last(set: RangeInclusiveMap) { assert_eq!( set.last_range_value(), set.iter().max_by_key(|(range, _)| range.end()) ); } #[proptest] fn test_iter_reversible(set: RangeInclusiveMap) { let forward: Vec<_> = set.iter().collect(); let mut backward: Vec<_> = set.iter().rev().collect(); backward.reverse(); assert_eq!(forward, backward); } #[proptest] fn test_into_iter_reversible(set: RangeInclusiveMap) { let forward: Vec<_> = set.clone().into_iter().collect(); let mut backward: Vec<_> = set.into_iter().rev().collect(); backward.reverse(); assert_eq!(forward, backward); } #[proptest] fn test_overlapping_reversible( set: RangeInclusiveMap, range: RangeInclusive, ) { let forward: Vec<_> = set.overlapping(&range).collect(); let mut backward: Vec<_> = set.overlapping(&range).rev().collect(); backward.reverse(); assert_eq!(forward, backward); } #[proptest] fn test_arbitrary_map_u8(ranges: Vec<(RangeInclusive, String)>) { let ranges: Vec<_> = ranges .into_iter() .filter(|(range, _value)| range.start() != range.end()) .collect(); let set = ranges .iter() .fold(RangeInclusiveMap::new(), |mut set, (range, value)| { set.insert(range.clone(), value.clone()); set }); for value in 0..u8::MAX { assert_eq!( set.get(&value), ranges .iter() .rev() .find(|(range, _value)| range.contains(&value)) .map(|(_range, value)| value) ); } } #[proptest] #[allow(deprecated)] fn test_hash(left: RangeInclusiveMap, right: RangeInclusiveMap) { use core::hash::{Hash, Hasher, SipHasher}; let hash = |set: &RangeInclusiveMap<_, _>| { let mut hasher = SipHasher::new(); set.hash(&mut hasher); hasher.finish() }; if left == right { assert!( hash(&left) == hash(&right), "if two values are equal, their hash must be equal" ); } // if the hashes are equal the values might not be the same (collision) if hash(&left) != hash(&right) { assert!( left != right, "if two value's hashes are not equal, they must not be equal" ); } } #[proptest] fn test_ord(left: RangeInclusiveMap, right: RangeInclusiveMap) { assert_eq!( left == right, left.cmp(&right).is_eq(), "ordering and equality must match" ); assert_eq!( left.cmp(&right), left.partial_cmp(&right).unwrap(), "ordering is total for ordered parameters" ); } #[test] fn test_from_array() { let mut map = RangeInclusiveMap::new(); map.insert(0..=100, "hello"); map.insert(200..=300, "world"); assert_eq!( map, RangeInclusiveMap::from([(0..=100, "hello"), (200..=300, "world")]) ); } #[test] fn test_macro() { assert_eq!( range_inclusive_map![], RangeInclusiveMap::::default() ); assert_eq!( range_inclusive_map!(0..=100 => "abc", 100..=200 => "def", 200..=300 => "ghi"), [(0..=100, "abc"), (100..=200, "def"), (200..=300, "ghi")] .iter() .cloned() .collect(), ); } trait RangeInclusiveMapExt { fn to_vec(&self) -> Vec<(RangeInclusive, V)>; } impl RangeInclusiveMapExt for RangeInclusiveMap where K: Ord + Clone + StepLite, V: Eq + Clone, { fn to_vec(&self) -> Vec<(RangeInclusive, V)> { self.iter().map(|(kr, v)| (kr.clone(), v.clone())).collect() } } // // Insertion tests // #[test] fn empty_map_is_empty() { let range_map: RangeInclusiveMap = RangeInclusiveMap::new(); assert_eq!(range_map.to_vec(), vec![]); } #[test] fn insert_into_empty_map() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(0..=50, false); assert_eq!(range_map.to_vec(), vec![(0..=50, false)]); } #[test] fn new_same_value_immediately_following_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●---● ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(1..=3, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ●---◌ ◌ ◌ ◌ range_map.insert(4..=6, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●---------◌ ◌ ◌ ◌ assert_eq!(range_map.to_vec(), vec![(1..=6, false)]); } #[test] fn new_different_value_immediately_following_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●---● ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(1..=3, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◆---◇ ◌ ◌ ◌ range_map.insert(4..=6, true); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●---● ◌ ◌ ◌ ◌ ◌ ◌ // ◌ ◌ ◌ ◌ ◆---◇ ◌ ◌ ◌ assert_eq!(range_map.to_vec(), vec![(1..=3, false), (4..=6, true)]); } #[test] fn new_same_value_overlapping_end_of_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●-----● ◌ ◌ ◌ ◌ ◌ range_map.insert(1..=4, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ●---● ◌ ◌ ◌ range_map.insert(4..=6, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●---------● ◌ ◌ ◌ assert_eq!(range_map.to_vec(), vec![(1..=6, false)]); } #[test] fn new_different_value_overlapping_end_of_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●---● ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(1..=3, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◆---◆ ◌ ◌ ◌ ◌ range_map.insert(3..=5, true); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●-● ◌ ◌ ◌ ◌ ◌ ◌ ◌ // ◌ ◌ ◌ ◆---◇ ◌ ◌ ◌ ◌ assert_eq!(range_map.to_vec(), vec![(1..=2, false), (3..=5, true)]); } #[test] fn new_same_value_immediately_preceding_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ●---● ◌ ◌ ◌ ◌ range_map.insert(3..=5, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●-● ◌ ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(1..=2, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●-------● ◌ ◌ ◌ ◌ assert_eq!(range_map.to_vec(), vec![(1..=5, false)]); } #[test] fn new_different_value_immediately_preceding_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◆---◆ ◌ ◌ ◌ ◌ range_map.insert(3..=5, true); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●-● ◌ ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(1..=2, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●-● ◌ ◌ ◌ ◌ ◌ ◌ ◌ // ◌ ◌ ◌ ◆---◇ ◌ ◌ ◌ ◌ assert_eq!(range_map.to_vec(), vec![(1..=2, false), (3..=5, true)]); } #[test] fn new_same_value_wholly_inside_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●-------● ◌ ◌ ◌ ◌ range_map.insert(1..=5, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ●---● ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(2..=4, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●-------● ◌ ◌ ◌ ◌ assert_eq!(range_map.to_vec(), vec![(1..=5, false)]); } #[test] fn new_different_value_wholly_inside_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◆-------◆ ◌ ◌ ◌ ◌ range_map.insert(1..=5, true); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ●---● ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(2..=4, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◆ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ // ◌ ◌ ●---● ◌ ◌ ◌ ◌ ◌ // ◌ ◌ ◌ ◌ ◌ ◆ ◌ ◌ ◌ ◌ assert_eq!( range_map.to_vec(), vec![(1..=1, true), (2..=4, false), (5..=5, true)] ); } #[test] fn replace_at_end_of_existing_range_should_coalesce() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●---● ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(1..=3, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ●---● ◌ ◌ ◌ range_map.insert(4..=6, true); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ●---● ◌ ◌ ◌ range_map.insert(4..=6, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●---------● ◌ ◌ ◌ assert_eq!(range_map.to_vec(), vec![(1..=6, false)]); } #[test] // Test every permutation of a bunch of touching and overlapping ranges. fn lots_of_interesting_ranges() { use crate::dense::DenseU32RangeMap; use permutator::Permutation; let mut ranges_with_values = [ (2..=3, false), // A duplicate range (2..=3, false), // Almost a duplicate, but with a different value (2..=3, true), // A few small ranges, some of them overlapping others, // some of them touching others (3..=5, true), (4..=6, true), (6..=7, true), // A really big range (2..=6, true), ]; ranges_with_values.permutation().for_each(|permutation| { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); let mut dense: DenseU32RangeMap = DenseU32RangeMap::new(); for (k, v) in permutation { // Insert it into both maps. range_map.insert(k.clone(), v); dense.insert(k, v); // At every step, both maps should contain the same stuff. let sparse = range_map.to_vec(); let dense = dense.to_vec(); assert_eq!(sparse, dense); } }); } // // Get* tests // #[test] fn get() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(0..=50, false); assert_eq!(range_map.get(&50), Some(&false)); assert_eq!(range_map.get(&51), None); } #[test] fn get_key_value() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(0..=50, false); assert_eq!(range_map.get_key_value(&50), Some((&(0..=50), &false))); assert_eq!(range_map.get_key_value(&51), None); } // // Removal tests // #[test] fn remove_from_empty_map() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.remove(0..=50); assert_eq!(range_map.to_vec(), vec![]); } #[test] fn remove_non_covered_range_before_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(25..=75, false); range_map.remove(0..=24); assert_eq!(range_map.to_vec(), vec![(25..=75, false)]); } #[test] fn remove_non_covered_range_after_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(25..=75, false); range_map.remove(76..=100); assert_eq!(range_map.to_vec(), vec![(25..=75, false)]); } #[test] fn remove_overlapping_start_of_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(25..=75, false); range_map.remove(0..=25); assert_eq!(range_map.to_vec(), vec![(26..=75, false)]); } #[test] fn remove_middle_of_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(25..=75, false); range_map.remove(30..=70); assert_eq!(range_map.to_vec(), vec![(25..=29, false), (71..=75, false)]); } #[test] fn remove_overlapping_end_of_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(25..=75, false); range_map.remove(75..=100); assert_eq!(range_map.to_vec(), vec![(25..=74, false)]); } #[test] fn remove_exactly_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(25..=75, false); range_map.remove(25..=75); assert_eq!(range_map.to_vec(), vec![]); } #[test] fn remove_superset_of_stored() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(25..=75, false); range_map.remove(0..=100); assert_eq!(range_map.to_vec(), vec![]); } // // Test extremes of key ranges; we do addition/subtraction in // the range domain so I want to make sure I haven't accidentally // introduced some arithmetic overflow there. // #[test] fn no_overflow_at_key_domain_extremes() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(0..=255, false); range_map.insert(0..=10, true); range_map.insert(245..=255, true); range_map.remove(0..=5); range_map.remove(0..=5); range_map.remove(250..=255); range_map.remove(250..=255); range_map.insert(0..=255, true); range_map.remove(1..=254); range_map.insert(254..=254, true); range_map.insert(255..=255, true); range_map.insert(255..=255, false); range_map.insert(0..=0, false); range_map.insert(1..=1, true); range_map.insert(0..=0, true); } // Gaps tests #[test] fn whole_range_is_a_gap() { // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ let range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◆-------------◆ ◌ let outer_range = 1..=8; let mut gaps = range_map.gaps(&outer_range); // Should yield the entire outer range. assert_eq!(gaps.next(), Some(1..=8)); assert_eq!(gaps.next(), None); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn whole_range_is_covered_exactly() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●---------● ◌ ◌ ◌ range_map.insert(1..=6, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◆---------◆ ◌ ◌ ◌ let outer_range = 1..=6; let mut gaps = range_map.gaps(&outer_range); // Should yield no gaps. assert_eq!(gaps.next(), None); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn item_before_outer_range() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●---● ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(1..=3, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◆-----◆ ◌ let outer_range = 5..=8; let mut gaps = range_map.gaps(&outer_range); // Should yield the entire outer range. assert_eq!(gaps.next(), Some(5..=8)); assert_eq!(gaps.next(), None); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn item_touching_start_of_outer_range() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●-----● ◌ ◌ ◌ ◌ ◌ range_map.insert(1..=4, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◆-----◆ ◌ let outer_range = 5..=8; let mut gaps = range_map.gaps(&outer_range); // Should yield the entire outer range. assert_eq!(gaps.next(), Some(5..=8)); assert_eq!(gaps.next(), None); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn item_overlapping_start_of_outer_range() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●-------● ◌ ◌ ◌ ◌ range_map.insert(1..=5, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◆-----◆ ◌ let outer_range = 5..=8; let mut gaps = range_map.gaps(&outer_range); // Should yield from just past the end of the stored item // to the end of the outer range. assert_eq!(gaps.next(), Some(6..=8)); assert_eq!(gaps.next(), None); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn item_starting_at_start_of_outer_range() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ●-● ◌ ◌ ◌ range_map.insert(5..=6, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◆-----◆ ◌ let outer_range = 5..=8; let mut gaps = range_map.gaps(&outer_range); // Should yield from just past the item onwards. assert_eq!(gaps.next(), Some(7..=8)); assert_eq!(gaps.next(), None); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn items_floating_inside_outer_range() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◌ ●-● ◌ ◌ range_map.insert(6..=7, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ●-● ◌ ◌ ◌ ◌ ◌ range_map.insert(3..=4, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◆-------------◆ ◌ let outer_range = 1..=8; let mut gaps = range_map.gaps(&outer_range); // Should yield gaps at start, between items, // and at end. assert_eq!(gaps.next(), Some(1..=2)); assert_eq!(gaps.next(), Some(5..=5)); assert_eq!(gaps.next(), Some(8..=8)); assert_eq!(gaps.next(), None); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn item_ending_at_end_of_outer_range() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◌ ◌ ●-● ◌ range_map.insert(7..=8, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◆-----◆ ◌ let outer_range = 5..=8; let mut gaps = range_map.gaps(&outer_range); // Should yield from the start of the outer range // up to just before the start of the stored item. assert_eq!(gaps.next(), Some(5..=6)); assert_eq!(gaps.next(), None); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn item_overlapping_end_of_outer_range() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ●---● ◌ ◌ range_map.insert(5..=6, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◆-----◆ ◌ ◌ ◌ ◌ let outer_range = 2..=5; let mut gaps = range_map.gaps(&outer_range); // Should yield from the start of the outer range // up to the start of the stored item. assert_eq!(gaps.next(), Some(2..=4)); assert_eq!(gaps.next(), None); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn item_touching_end_of_outer_range() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ●-----● ◌ range_map.insert(5..=9, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◆-----◆ ◌ ◌ ◌ ◌ ◌ let outer_range = 1..=4; let mut gaps = range_map.gaps(&outer_range); // Should yield the entire outer range. assert_eq!(gaps.next(), Some(1..=4)); assert_eq!(gaps.next(), None); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn item_after_outer_range() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◌ ●---● ◌ range_map.insert(6..=7, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◆-----◆ ◌ ◌ ◌ ◌ ◌ let outer_range = 1..=4; let mut gaps = range_map.gaps(&outer_range); // Should yield the entire outer range. assert_eq!(gaps.next(), Some(1..=4)); assert_eq!(gaps.next(), None); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn zero_width_outer_range_with_items_away_from_both_sides() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◆---◆ ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(1..=3, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◆---◆ ◌ ◌ range_map.insert(5..=7, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◆ ◌ ◌ ◌ ◌ ◌ let outer_range = 4..=4; let mut gaps = range_map.gaps(&outer_range); // Should yield a zero-width gap. assert_eq!(gaps.next(), Some(4..=4)); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn zero_width_outer_range_with_items_touching_both_sides() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◆-◆ ◌ ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(2..=3, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◆---◆ ◌ ◌ ◌ range_map.insert(5..=6, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◆ ◌ ◌ ◌ ◌ ◌ let outer_range = 4..=4; let mut gaps = range_map.gaps(&outer_range); // Should yield no gaps. assert_eq!(gaps.next(), Some(4..=4)); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn empty_outer_range_with_item_straddling() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◆-----◆ ◌ ◌ ◌ ◌ ◌ range_map.insert(2..=5, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◆ ◌ ◌ ◌ ◌ ◌ let outer_range = 4..=4; let mut gaps = range_map.gaps(&outer_range); // Should yield no gaps. assert_eq!(gaps.next(), None); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn no_empty_gaps() { // Make two ranges different values so they don't // get coalesced. let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◆-◆ ◌ ◌ ◌ ◌ range_map.insert(4..=5, true); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◆-◆ ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(2..=3, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ●-------------● ◌ let outer_range = 1..=8; let mut gaps = range_map.gaps(&outer_range); // Should yield gaps at start and end, but not between the // two touching items. assert_eq!(gaps.next(), Some(1..=1)); assert_eq!(gaps.next(), Some(6..=8)); assert_eq!(gaps.next(), None); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } #[test] fn no_overflow_finding_gaps_at_key_domain_extremes() { // Items and outer range both at extremes. let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(0..=255, false); range_map.gaps(&(0..=255)); // Items at extremes with gaps in middle. let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(0..=255, false); range_map.gaps(&(0..=5)); range_map.gaps(&(250..=255)); // Items just in from extremes. let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(0..=255, false); range_map.gaps(&(1..=5)); range_map.gaps(&(250..=254)); // Outer range just in from extremes, // items at extremes. let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(1..=254, false); range_map.gaps(&(0..=5)); range_map.gaps(&(250..=255)); } #[test] fn adjacent_unit_width_items() { // Items two items next to each other at the start, and at the end. let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); range_map.insert(0..=0, false); range_map.insert(1..=1, true); range_map.insert(254..=254, false); range_map.insert(255..=255, true); let outer_range = 0..=255; let mut gaps = range_map.gaps(&outer_range); // Should yield one big gap in the middle. assert_eq!(gaps.next(), Some(2..=253)); // Gaps iterator should be fused. assert_eq!(gaps.next(), None); assert_eq!(gaps.next(), None); } // Overlapping tests #[test] fn overlapping_ref_with_empty_map() { // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ let range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◆-------------◆ ◌ let query_range = 1..=8; let mut overlapping = range_map.overlapping(&query_range); // Should not yield any items. assert_eq!(overlapping.next(), None); // Gaps iterator should be fused. assert_eq!(overlapping.next(), None); } #[test] fn overlapping_owned_with_empty_map() { // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ let range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◆-------------◆ ◌ let query_range = 1..=8; let mut overlapping = range_map.overlapping(query_range); // Should not yield any items. assert_eq!(overlapping.next(), None); // Gaps iterator should be fused. assert_eq!(overlapping.next(), None); } #[test] fn overlapping_partial_edges_complete_middle() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ●-● ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(0..=1, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ●-● ◌ ◌ ◌ ◌ ◌ range_map.insert(3..=4, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◌ ●-● ◌ ◌ range_map.insert(6..=7, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◆---------◆ ◌ ◌ ◌ let query_range = 1..=6; let mut overlapping = range_map.overlapping(&query_range); // Should yield partially overlapped range at start. assert_eq!(overlapping.next(), Some((&(0..=1), &()))); // Should yield completely overlapped range in middle. assert_eq!(overlapping.next(), Some((&(3..=4), &()))); // Should yield partially overlapped range at end. assert_eq!(overlapping.next(), Some((&(6..=7), &()))); // Gaps iterator should be fused. assert_eq!(overlapping.next(), None); assert_eq!(overlapping.next(), None); } #[test] fn overlapping_non_overlapping_edges_complete_middle() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ●-● ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(0..=1, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ●-● ◌ ◌ ◌ ◌ ◌ range_map.insert(3..=4, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◌ ●-● ◌ ◌ range_map.insert(6..=7, ()); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◆-----◆ ◌ ◌ ◌ ◌ let query_range = 2..=5; let mut overlapping = range_map.overlapping(&query_range); // Should only yield the completely overlapped range in middle. // (Not the ranges that are touched by not covered to either side.) assert_eq!(overlapping.next(), Some((&(3..=4), &()))); // Gaps iterator should be fused. assert_eq!(overlapping.next(), None); assert_eq!(overlapping.next(), None); } /// /// impl Debug /// #[test] fn map_debug_repr_looks_right() { let mut map: RangeInclusiveMap = RangeInclusiveMap::new(); // Empty assert_eq!(format!("{:?}", map), "{}"); // One entry map.insert(2..=5, ()); assert_eq!(format!("{:?}", map), "{2..=5: ()}"); // Many entries map.insert(7..=8, ()); map.insert(10..=11, ()); assert_eq!(format!("{:?}", map), "{2..=5: (), 7..=8: (), 10..=11: ()}"); } // impl Default where T: ?Default #[test] fn always_default() { struct NoDefault; RangeInclusiveMap::::default(); } // impl Serialize #[cfg(feature = "serde1")] #[test] fn serialization() { let mut range_map: RangeInclusiveMap = RangeInclusiveMap::new(); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◆---◆ ◌ ◌ ◌ ◌ ◌ ◌ range_map.insert(1..=3, false); // 0 1 2 3 4 5 6 7 8 9 // ◌ ◌ ◌ ◌ ◌ ◆---◆ ◌ ◌ range_map.insert(5..=7, true); let output = serde_json::to_string(&range_map).expect("Failed to serialize"); assert_eq!(output, "[[[1,3],false],[[5,7],true]]"); } // impl Deserialize #[cfg(feature = "serde1")] #[test] fn deserialization() { let input = "[[[1,3],false],[[5,7],true]]"; let range_map: RangeInclusiveMap = serde_json::from_str(input).expect("Failed to deserialize"); let reserialized = serde_json::to_string(&range_map).expect("Failed to re-serialize"); assert_eq!(reserialized, input); } // const fn #[cfg(feature = "const_fn")] const _MAP: RangeInclusiveMap = RangeInclusiveMap::new(); #[cfg(feature = "const_fn")] const _MAP2: RangeInclusiveMap = RangeInclusiveMap::new_with_step_fns(); #[cfg(feature = "quickcheck")] quickcheck::quickcheck! { fn prop(xs: RangeInclusiveMap) -> bool { xs == xs } } }