Skip to content

Commit

Permalink
Merge pull request #76 from xfbs/patrick/overlapping
Browse files Browse the repository at this point in the history
Allow the `overlapping()` function to take ranges by value
  • Loading branch information
jeffparsons authored Jan 30, 2024
2 parents b9add4f + 252dedd commit 8b2ee44
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 26 deletions.
38 changes: 29 additions & 9 deletions src/inclusive_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ 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::iter::FromIterator;
Expand Down Expand Up @@ -527,11 +528,12 @@ where

/// Gets an iterator over all the stored ranges that are
/// either partially or completely overlapped by the given range.
pub fn overlapping<'a>(&'a self, range: &'a RangeInclusive<K>) -> Overlapping<K, V> {
pub fn overlapping<R: Borrow<RangeInclusive<K>>>(&self, range: R) -> Overlapping<K, V, R> {
// 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.start().clone()..=range.start().clone());
let start_sliver = RangeInclusiveEndWrapper::new(
range.borrow().start().clone()..=range.borrow().start().clone(),
);
let btm_range_iter = self
.btm
.range::<RangeInclusiveEndWrapper<K>, RangeFrom<&RangeInclusiveEndWrapper<K>>>(
Expand Down Expand Up @@ -811,23 +813,26 @@ where
/// documentation for more.
///
/// [`overlapping`]: RangeInclusiveMap::overlapping
pub struct Overlapping<'a, K, V> {
query_range: &'a RangeInclusive<K>,
pub struct Overlapping<'a, K, V, R: Borrow<RangeInclusive<K>> = &'a RangeInclusive<K>> {
query_range: R,
btm_range_iter: alloc::collections::btree_map::Range<'a, RangeInclusiveStartWrapper<K>, V>,
}

// `Overlapping` is always fused. (See definition of `next` below.)
impl<'a, K, V> core::iter::FusedIterator for Overlapping<'a, K, V> where K: Ord + Clone {}
impl<'a, K, V, R: Borrow<RangeInclusive<K>>> core::iter::FusedIterator for Overlapping<'a, K, V, R> where
K: Ord + Clone
{
}

impl<'a, K, V> Iterator for Overlapping<'a, K, V>
impl<'a, K, V, R: Borrow<RangeInclusive<K>>> Iterator for Overlapping<'a, K, V, R>
where
K: Ord + Clone,
{
type Item = (&'a RangeInclusive<K>, &'a V);

fn next(&mut self) -> Option<Self::Item> {
if let Some((k, v)) = self.btm_range_iter.next() {
if k.start() <= self.query_range.end() {
if k.start() <= self.query_range.borrow().end() {
Some((&k.range, v))
} else {
// The rest of the items in the underlying iterator
Expand Down Expand Up @@ -1503,7 +1508,7 @@ mod tests {
// Overlapping tests

#[test]
fn overlapping_with_empty_map() {
fn overlapping_ref_with_empty_map() {
// 0 1 2 3 4 5 6 7 8 9
// ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌
let range_map: RangeInclusiveMap<u32, ()> = RangeInclusiveMap::new();
Expand All @@ -1517,6 +1522,21 @@ mod tests {
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<u32, ()> = 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<u32, ()> = RangeInclusiveMap::new();
Expand Down
14 changes: 9 additions & 5 deletions src/inclusive_set.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt::{self, Debug};
use core::iter::FromIterator;
Expand Down Expand Up @@ -189,7 +190,7 @@ where
/// either partially or completely overlapped by the given range.
///
/// The iterator element type is `RangeInclusive<T>`.
pub fn overlapping<'a>(&'a self, range: &'a RangeInclusive<T>) -> Overlapping<T> {
pub fn overlapping<R: Borrow<RangeInclusive<T>>>(&self, range: R) -> Overlapping<T, R> {
Overlapping {
inner: self.rm.overlapping(range),
}
Expand Down Expand Up @@ -393,14 +394,17 @@ where
/// documentation for more.
///
/// [`overlapping`]: RangeInclusiveSet::overlapping
pub struct Overlapping<'a, T> {
inner: crate::inclusive_map::Overlapping<'a, T, ()>,
pub struct Overlapping<'a, T, R: Borrow<RangeInclusive<T>> = &'a RangeInclusive<T>> {
inner: crate::inclusive_map::Overlapping<'a, T, (), R>,
}

// `Overlapping` is always fused. (See definition of `next` below.)
impl<'a, T> core::iter::FusedIterator for Overlapping<'a, T> where T: Ord + Clone {}
impl<'a, T, R: Borrow<RangeInclusive<T>>> core::iter::FusedIterator for Overlapping<'a, T, R> where
T: Ord + Clone
{
}

impl<'a, T> Iterator for Overlapping<'a, T>
impl<'a, T, R: Borrow<RangeInclusive<T>>> Iterator for Overlapping<'a, T, R>
where
T: Ord + Clone,
{
Expand Down
19 changes: 12 additions & 7 deletions src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::range_wrapper::RangeStartWrapper;
use crate::range_wrapper::RangeEndWrapper;
use crate::std_ext::*;
use alloc::collections::BTreeMap;
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt::{self, Debug};
use core::iter::FromIterator;
Expand Down Expand Up @@ -177,10 +178,11 @@ where

/// Gets an iterator over all the stored ranges that are
/// either partially or completely overlapped by the given range.
pub fn overlapping<'a>(&'a self, range: &'a Range<K>) -> Overlapping<K, V> {
pub fn overlapping<R: Borrow<Range<K>>>(&self, range: R) -> Overlapping<K, V, R> {
// Find the first matching stored range by its _end_,
// using sneaky layering and `Borrow` implementation. (See `range_wrappers` module.)
let start_sliver = RangeEndWrapper::new(range.start.clone()..range.start.clone());
let start_sliver =
RangeEndWrapper::new(range.borrow().start.clone()..range.borrow().start.clone());
let btm_range_iter = self
.btm
.range::<RangeEndWrapper<K>, (Bound<&RangeEndWrapper<K>>, Bound<_>)>((
Expand Down Expand Up @@ -706,23 +708,26 @@ where
/// documentation for more.
///
/// [`overlapping`]: RangeMap::overlapping
pub struct Overlapping<'a, K, V> {
query_range: &'a Range<K>,
pub struct Overlapping<'a, K, V, R: Borrow<Range<K>> = &'a Range<K>> {
query_range: R,
btm_range_iter: alloc::collections::btree_map::Range<'a, RangeStartWrapper<K>, V>,
}

// `Overlapping` is always fused. (See definition of `next` below.)
impl<'a, K, V> core::iter::FusedIterator for Overlapping<'a, K, V> where K: Ord {}
impl<'a, K, V, R: Borrow<Range<K>>> core::iter::FusedIterator for Overlapping<'a, K, V, R> where
K: Ord
{
}

impl<'a, K, V> Iterator for Overlapping<'a, K, V>
impl<'a, K, V, R: Borrow<Range<K>>> Iterator for Overlapping<'a, K, V, R>
where
K: Ord,
{
type Item = (&'a Range<K>, &'a V);

fn next(&mut self) -> Option<Self::Item> {
if let Some((k, v)) = self.btm_range_iter.next() {
if k.start < self.query_range.end {
if k.start < self.query_range.borrow().end {
Some((&k.range, v))
} else {
// The rest of the items in the underlying iterator
Expand Down
14 changes: 9 additions & 5 deletions src/set.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt::{self, Debug};
use core::iter::FromIterator;
Expand Down Expand Up @@ -163,7 +164,7 @@ where
/// either partially or completely overlapped by the given range.
///
/// The iterator element type is `&Range<T>`.
pub fn overlapping<'a>(&'a self, range: &'a Range<T>) -> Overlapping<T> {
pub fn overlapping<R: Borrow<Range<T>>>(&self, range: R) -> Overlapping<T, R> {
Overlapping {
inner: self.rm.overlapping(range),
}
Expand Down Expand Up @@ -361,14 +362,17 @@ where
/// documentation for more.
///
/// [`overlapping`]: RangeSet::overlapping
pub struct Overlapping<'a, T> {
inner: crate::map::Overlapping<'a, T, ()>,
pub struct Overlapping<'a, T, R: Borrow<Range<T>> = &'a Range<T>> {
inner: crate::map::Overlapping<'a, T, (), R>,
}

// `Overlapping` is always fused. (See definition of `next` below.)
impl<'a, T> core::iter::FusedIterator for Overlapping<'a, T> where T: Ord + Clone {}
impl<'a, T, R: Borrow<Range<T>>> core::iter::FusedIterator for Overlapping<'a, T, R> where
T: Ord + Clone
{
}

impl<'a, T> Iterator for Overlapping<'a, T>
impl<'a, T, R: Borrow<Range<T>>> Iterator for Overlapping<'a, T, R>
where
T: Ord + Clone,
{
Expand Down

0 comments on commit 8b2ee44

Please sign in to comment.