blob: 0d94e882f454e87a215a8e24c70ed12ae2cdf296 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::ops::Range;
#[cfg(not(feature = "use_cowmap"))]
use std::collections::BTreeMap;
#[cfg(feature = "use_cowmap")]
use cowmap::CowMap;
/// Keys for the map inside RangeMap.
///
/// This object holds a Range but implements the ordering traits according to
/// the start of the range. Using this struct lets us store both ends of the
/// range in the BTreeMap and recover ranges by querying for their start point.
#[derive(Clone, Debug)]
struct RangeStart<T> {
range: Range<T>,
}
impl<T: Copy> RangeStart<T> {
/// Wrap the given range in a RangeStart.
///
/// Used in the BTreeMap to order the entries by the start of the range but
/// also remember the end of the range.
fn new(range: Range<T>) -> Self {
RangeStart { range }
}
/// An empty range with both endpoints at the start.
///
/// Used for queries into the BTreeMap, but never stored in the BTreeMap.
fn from_point(point: T) -> Self {
RangeStart { range: Range { start: point, end: point } }
}
}
/// PartialEq according to the start of the Range.
impl<T: PartialEq> PartialEq for RangeStart<T> {
fn eq(&self, other: &Self) -> bool {
self.range.start.eq(&other.range.start)
}
}
/// Eq according to the start of the Range.
impl<T: Eq> Eq for RangeStart<T> {}
/// PartialOrd according to the start of the Range.
impl<T: Ord> PartialOrd for RangeStart<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
/// Ord according to the start of the Range.
impl<T: Ord> Ord for RangeStart<T> {
fn cmp(&self, other: &Self) -> Ordering {
self.range.start.cmp(&other.range.start)
}
}
/// A map from a range of keys to values.
///
/// At any given time, the map contains a set of non-overlapping, non-empty
/// ranges of type K that are associated with values of type V.
///
/// A given range can be split into two separate ranges if some of the
/// intermediate values are removed from the map of if another value is
/// inserted over the intermediate values. When that happens, the value
/// for the split range is cloned using the Copy trait.
///
/// Adjacent ranges are not merged. Even if the value is "the same" (for some
/// definition of "the same"), the ranges are kept separately.
///
/// Querying a point in the map returns not only the value stored at that point
/// but also the range that value occupies in the map.
#[derive(Debug)]
pub struct RangeMap<K: Ord + Clone, V: Clone + Eq> {
#[cfg(not(feature = "use_cowmap"))]
map: BTreeMap<RangeStart<K>, V>,
#[cfg(feature = "use_cowmap")]
map: CowMap<RangeStart<K>, V, 8>,
}
impl<K, V> Default for RangeMap<K, V>
where
K: Ord + Copy,
V: Clone + Eq,
{
/// By default, a RangeMap is empty.
fn default() -> Self {
Self { map: Default::default() }
}
}
impl<K, V> RangeMap<K, V>
where
K: Ord + Copy,
V: Clone + Eq,
{
/// Returns the range (and associated value) that contains the given point,
/// if any.
///
/// At most one range and value can exist at a given point because the
/// ranges in the map are non-overlapping.
///
/// Empty ranges do not contain any points and therefore cannot be found
/// using this method. Rather than being stored in the map, values
/// associated with empty ranges are dropped.
pub fn get(&self, point: K) -> Option<(&Range<K>, &V)> {
self.map
.range(..=RangeStart::from_point(point))
.next_back()
.filter(|(k, _)| k.range.contains(&point))
.map(|(k, v)| (&k.range, v))
}
/// Inserts a range with the given value.
///
/// The keys included in the given range are now associated with the given
/// value. If those keys were previously associated with another value,
/// are no longer associated with that previous value.
///
/// This method can cause one or more values in the map to be dropped if
/// the all of the keys associated with those values are contained within
/// the given range.
///
/// If the inserted range is directly adjacent to another range with an equal value, the
/// inserted range will be merged with the adjacent ranges.
pub fn insert(&mut self, mut range: Range<K>, value: V) {
if range.end <= range.start {
return;
}
self.remove(range.clone());
// Check for a range directly before this one. If it exists, it will be the last range with
// start < range.start.
if let Some((prev_range, prev_value)) =
self.map.range(..RangeStart::from_point(range.start)).next_back()
{
let prev_range = &prev_range.range;
if prev_range.end == range.start && &value == prev_value {
range.start = prev_range.start.clone();
self.remove_exact_range(prev_range.clone());
}
}
// Check for a range directly after. If it exists, we can look it up by exact start value
// of range.end.
if let Some((next_range, next_value)) =
self.map.get_key_value(&RangeStart::from_point(range.end))
{
let next_range = &next_range.range;
if next_range.start == range.end && &value == next_value {
range.end = next_range.end.clone();
self.remove_exact_range(next_range.clone());
}
}
self.insert_into_empty_range(range, value);
}
/// Remove the given range from the map.
///
/// The keys included in the given range are no longer associated with any
/// values.
///
/// This method can cause one or more values in the map to be dropped if all of the keys
/// associated with those values are contained within the given range.
///
/// Returns any removed values.
pub fn remove(&mut self, range: Range<K>) -> Vec<V> {
let mut removed_values = vec![];
// If the given range is empty, there is nothing to do.
if range.end <= range.start {
return removed_values;
}
// Find the range (if any) that intersects the start of range.
//
// There can be at most one such range because we maintain the
// invariant that the ranges stored in the map are non-overlapping.
if let Some((old_range, v)) =
self.get(range.start).map(|(range, v)| (range.clone(), v.clone()))
{
// Remove that range from the map.
if let Some(value) = self.remove_exact_range(old_range.clone()) {
removed_values.push(value);
}
// If the removed range extends after the end of the given range,
// re-insert the part of the old range that extends beyond the end
// of the given range.
if old_range.end > range.end {
self.insert_into_empty_range(range.end.clone()..old_range.end, v.clone());
}
// If the removed range extends before the start of the given
// range, re-insert the part of the old range that extends before
// the start of the given range.
if old_range.start < range.start {
self.insert_into_empty_range(old_range.start..range.start.clone(), v);
}
// Notice that we can end up splitting the old range into two
// separate ranges if the old range extends both beyond the given
// range and before the given range.
}
// Find the range (if any) that intersects the end of range.
//
// There can be at most one such range because we maintain the
// invariant that the ranges stored in the map are non-overlapping.
//
// We exclude the end of the given range because a range that starts
// exactly at the end of the given range does not overalp the given
// range.
if let Some((old_range, v)) = self
.map
.range(RangeStart::from_point(range.start)..RangeStart::from_point(range.end))
.next_back()
.filter(|(k, _)| k.range.contains(&range.end))
.map(|(k, v)| (k.range.clone(), v.clone()))
{
// Remove that range from the map.
if let Some(value) = self.remove_exact_range(old_range.clone()) {
removed_values.push(value);
}
// If the removed range extends after the end of the given range,
// re-insert the part of the old range that extends beyond the end
// of the given range.
if old_range.end > range.end {
self.insert_into_empty_range(range.end.clone()..old_range.end, v);
}
}
// Remove any remaining ranges that are contained within the range.
//
// These ranges cannot possibly extend beyond the given range because
// we will have already removed them from the map at this point.
//
// We collect the doomed keys into a Vec to avoid mutating the map
// during the iteration.
let doomed: Vec<_> = self
.map
.range(RangeStart::from_point(range.start)..RangeStart::from_point(range.end))
.map(|(k, _)| k.clone())
.collect();
for key in &doomed {
if let Some(removed_value) = self.map.remove(key) {
removed_values.push(removed_value);
}
}
removed_values
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
/// Iterate over the ranges in the map.
pub fn iter(&self) -> impl Iterator<Item = (&Range<K>, &V)> {
self.map.iter().map(|(k, value)| (&k.range, value))
}
/// Iterate over the ranges in the map, starting at the first range starting after or at the given point.
pub fn iter_starting_at(&self, point: K) -> impl Iterator<Item = (&Range<K>, &V)> {
self.map.range(RangeStart::from_point(point)..).map(|(k, value)| (&k.range, value))
}
/// Iterate over the ranges in the map, starting at the last range starting before or at the given point.
pub fn iter_ending_at(&self, point: K) -> impl DoubleEndedIterator<Item = (&Range<K>, &V)> {
self.map.range(..RangeStart::from_point(point)).map(|(k, value)| (&k.range, value))
}
/// Iterate over the ranges in the map that intersect the requested range.
pub fn intersection<R>(&self, range: R) -> impl Iterator<Item = (&Range<K>, &V)>
where
R: Borrow<Range<K>>,
{
let range = range.borrow();
let start = self.get(range.start).map(|(r, _)| r.start).unwrap_or(range.start);
self.map
.range(RangeStart::from_point(start)..RangeStart::from_point(range.end))
.map(|(k, value)| (&k.range, value))
}
/// Returns the final range in the map.
pub fn last_range(&self) -> Option<Range<K>> {
if let Some((r, _)) = self.map.last_key_value() {
Some(r.range.clone())
} else {
None
}
}
/// Associate the keys in the given range with the given value.
///
/// Callers must ensure that the keys in the given range are not already
/// associated with any values.
fn insert_into_empty_range(&mut self, range: Range<K>, value: V) {
self.map.insert(RangeStart::new(range), value);
}
/// Remove the given range from the map.
///
/// Callers must ensure that the exact range provided as an argument is
/// contained in the map.
fn remove_exact_range(&mut self, range: Range<K>) -> Option<V> {
self.map.remove(&RangeStart::new(range))
}
}
#[cfg(test)]
mod test {
use super::*;
#[::fuchsia::test]
fn test_empty() {
let mut map = RangeMap::<u32, i32>::default();
assert!(map.get(12).is_none());
map.remove(10..34);
// This is a test to make sure we can handle reversed ranges
#[allow(clippy::reversed_empty_ranges)]
map.remove(34..10);
}
#[::fuchsia::test]
fn test_insert_into_empty() {
let mut map = RangeMap::<u32, i32>::default();
map.insert(10..34, -14);
assert_eq!((&(10..34), &-14), map.get(12).unwrap());
assert_eq!((&(10..34), &-14), map.get(10).unwrap());
assert!(map.get(9).is_none());
assert_eq!((&(10..34), &-14), map.get(33).unwrap());
assert!(map.get(34).is_none());
}
#[::fuchsia::test]
fn test_iter() {
let mut map = RangeMap::<u32, i32>::default();
map.insert(10..34, -14);
map.insert(74..92, -12);
let mut iter = map.iter();
assert_eq!(iter.next().expect("missing elem"), (&(10..34), &-14));
assert_eq!(iter.next().expect("missing elem"), (&(74..92), &-12));
assert!(iter.next().is_none());
let mut iter = map.iter_starting_at(10);
assert_eq!(iter.next().expect("missing elem"), (&(10..34), &-14));
let mut iter = map.iter_starting_at(11);
assert_eq!(iter.next().expect("missing elem"), (&(74..92), &-12));
let mut iter = map.iter_starting_at(74);
assert_eq!(iter.next().expect("missing elem"), (&(74..92), &-12));
let mut iter = map.iter_starting_at(75);
assert_eq!(iter.next(), None);
assert_eq!(map.iter_ending_at(9).collect::<Vec<_>>(), vec![]);
assert_eq!(map.iter_ending_at(34).collect::<Vec<_>>(), vec![(&(10..34), &-14)]);
assert_eq!(map.iter_ending_at(74).collect::<Vec<_>>(), vec![(&(10..34), &-14)]);
assert_eq!(
map.iter_ending_at(75).collect::<Vec<_>>(),
vec![(&(10..34), &-14), (&(74..92), &-12)]
);
assert_eq!(
map.iter_ending_at(91).collect::<Vec<_>>(),
vec![(&(10..34), &-14), (&(74..92), &-12)]
);
assert_eq!(
map.iter_ending_at(92).collect::<Vec<_>>(),
vec![(&(10..34), &-14), (&(74..92), &-12)]
);
}
#[::fuchsia::test]
fn test_remove_overlapping_edge() {
let mut map = RangeMap::<u32, i32>::default();
map.insert(10..34, -14);
map.remove(2..11);
assert_eq!((&(11..34), &-14), map.get(11).unwrap());
map.remove(33..42);
assert_eq!((&(11..33), &-14), map.get(12).unwrap());
}
#[::fuchsia::test]
fn test_remove_middle_splits_range() {
let mut map = RangeMap::<u32, i32>::default();
map.insert(10..34, -14);
map.remove(15..18);
assert_eq!((&(10..15), &-14), map.get(12).unwrap());
assert_eq!((&(18..34), &-14), map.get(20).unwrap());
}
#[::fuchsia::test]
fn test_remove_upper_half_of_split_range_leaves_lower_range() {
let mut map = RangeMap::<u32, i32>::default();
map.insert(10..34, -14);
map.remove(15..18);
map.insert(2..7, -21);
map.remove(20..42);
assert_eq!((&(2..7), &-21), map.get(5).unwrap());
assert_eq!((&(10..15), &-14), map.get(12).unwrap());
}
#[::fuchsia::test]
fn test_range_map_overlapping_insert() {
let mut map = RangeMap::<u32, i32>::default();
map.insert(2..7, -21);
map.insert(5..9, -42);
map.insert(1..3, -43);
map.insert(6..8, -44);
assert_eq!((&(1..3), &-43), map.get(2).unwrap());
assert_eq!((&(3..5), &-21), map.get(4).unwrap());
assert_eq!((&(5..6), &-42), map.get(5).unwrap());
assert_eq!((&(6..8), &-44), map.get(7).unwrap());
}
#[::fuchsia::test]
fn test_intersect_single() {
let mut map = RangeMap::<u32, i32>::default();
map.insert(2..7, -10);
let mut iter = map.intersection(3..4);
assert_eq!(iter.next(), Some((&(2..7), &-10)));
assert_eq!(iter.next(), None);
let mut iter = map.intersection(2..3);
assert_eq!(iter.next(), Some((&(2..7), &-10)));
assert_eq!(iter.next(), None);
let mut iter = map.intersection(1..4);
assert_eq!(iter.next(), Some((&(2..7), &-10)));
assert_eq!(iter.next(), None);
let mut iter = map.intersection(1..2);
assert_eq!(iter.next(), None);
let mut iter = map.intersection(6..7);
assert_eq!(iter.next(), Some((&(2..7), &-10)));
assert_eq!(iter.next(), None);
}
#[::fuchsia::test]
fn test_intersect_multiple() {
let mut map = RangeMap::<u32, i32>::default();
map.insert(2..7, -10);
map.insert(7..9, -20);
map.insert(10..11, -30);
let mut iter = map.intersection(3..8);
assert_eq!(iter.next(), Some((&(2..7), &-10)));
assert_eq!(iter.next(), Some((&(7..9), &-20)));
assert_eq!(iter.next(), None);
let mut iter = map.intersection(3..11);
assert_eq!(iter.next(), Some((&(2..7), &-10)));
assert_eq!(iter.next(), Some((&(7..9), &-20)));
assert_eq!(iter.next(), Some((&(10..11), &-30)));
assert_eq!(iter.next(), None);
}
#[::fuchsia::test]
fn test_intersect_no_gaps() {
let mut map = RangeMap::<u32, i32>::default();
map.insert(0..1, -10);
map.insert(1..2, -20);
map.insert(2..3, -30);
let mut iter = map.intersection(0..3);
assert_eq!(iter.next(), Some((&(0..1), &-10)));
assert_eq!(iter.next(), Some((&(1..2), &-20)));
assert_eq!(iter.next(), Some((&(2..3), &-30)));
assert_eq!(iter.next(), None);
}
#[test]
fn test_merging() {
let mut map = RangeMap::<u32, i32>::default();
map.insert(1..2, -10);
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&(1..2), &-10)]);
map.insert(3..4, -10);
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&(1..2), &-10), (&(3..4), &-10)]);
map.insert(2..3, -10);
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&(1..4), &-10)]);
map.insert(0..1, -10);
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&(0..4), &-10)]);
map.insert(4..5, -10);
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&(0..5), &-10)]);
map.insert(2..3, -20);
assert_eq!(
map.iter().collect::<Vec<_>>(),
vec![(&(0..2), &-10), (&(2..3), &-20), (&(3..5), &-10)]
);
}
#[test]
fn test_remove_multiple_ranges_exact_query() {
let first = 15..21;
let second = first.end..29;
let mut map = RangeMap::default();
map.insert(first.clone(), 1);
map.insert(second.clone(), 2);
assert_eq!(map.remove(first.start..second.end), &[1, 2]);
}
}