#![forbid(unsafe_code)]
mod insert;
mod intersection;
pub mod interval;
mod remove;
#[cfg(test)]
mod tests;
use alloc::collections::vec_deque::{self, VecDeque};
use core::{
fmt,
iter::FromIterator,
num::NonZeroUsize,
ops::{Bound, Range, RangeBounds, RangeInclusive},
};
use insert::insert;
pub use intersection::Intersection;
pub use interval::*;
use remove::remove;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub enum IntervalSetError {
LimitExceeded,
InvalidInterval,
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct IntervalSet<T> {
limit: Option<NonZeroUsize>,
intervals: VecDeque<Interval<T>>,
}
impl<T> Default for IntervalSet<T> {
fn default() -> Self {
Self {
limit: None,
intervals: VecDeque::new(),
}
}
}
impl<T> IntervalSet<T> {
#[inline]
pub fn new() -> IntervalSet<T> {
Self::default()
}
#[inline]
pub fn with_capacity(capacity: usize) -> IntervalSet<T> {
let intervals = VecDeque::with_capacity(capacity);
IntervalSet {
limit: None,
intervals,
}
}
#[inline]
pub fn with_limit(limit: NonZeroUsize) -> IntervalSet<T> {
let mut set = Self::default();
set.set_limit(limit);
set
}
#[inline]
pub fn set_limit(&mut self, limit: NonZeroUsize) {
self.limit = Some(limit);
}
#[inline]
pub fn remove_limit(&mut self) {
self.limit = None;
}
#[inline]
pub fn interval_len(&self) -> usize {
self.intervals.len()
}
#[inline]
pub fn capacity(&self) -> usize {
self.intervals.capacity()
}
#[inline]
pub fn clear(&mut self) {
self.intervals.clear()
}
#[inline]
pub fn pop_min(&mut self) -> Option<Interval<T>> {
self.intervals.pop_front()
}
}
impl<T: IntervalBound> IntervalSet<T> {
#[inline]
pub fn count(&self) -> usize {
self.intervals.iter().map(|interval| interval.len()).sum()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.intervals.is_empty()
}
#[inline]
pub fn insert<R: RangeBounds<T>>(&mut self, interval: R) -> Result<(), IntervalSetError> {
let interval = Interval::from_range_bounds(interval)?;
if self.intervals.is_empty() {
self.intervals.push_front(interval);
return Ok(());
}
let index = self.index_for(&interval);
insert(&mut self.intervals, interval, index, self.limit)?;
self.check_integrity();
Ok(())
}
#[inline]
pub fn insert_front<R: RangeBounds<T>>(&mut self, interval: R) -> Result<(), IntervalSetError> {
let interval = Interval::from_range_bounds(interval)?;
if self.intervals.is_empty() {
self.intervals.push_front(interval);
return Ok(());
}
insert(&mut self.intervals, interval, 0, self.limit)?;
self.check_integrity();
Ok(())
}
#[inline]
pub fn insert_value(&mut self, value: T) -> Result<(), IntervalSetError> {
self.insert((Bound::Included(value), Bound::Included(value)))
}
#[inline]
pub fn union(&mut self, other: &Self) -> Result<(), IntervalSetError> {
if self.intervals.is_empty() {
self.intervals.clone_from(&other.intervals);
return Ok(());
}
self.set_operation(other, insert)
}
#[inline]
pub fn remove<R: RangeBounds<T>>(&mut self, interval: R) -> Result<(), IntervalSetError> {
let interval = Interval::from_range_bounds(interval)?;
if self.intervals.is_empty() {
return Ok(());
}
let index = self.index_for(&interval);
remove(&mut self.intervals, interval, index, self.limit)?;
self.check_integrity();
Ok(())
}
#[inline]
pub fn remove_value(&mut self, value: T) -> Result<(), IntervalSetError> {
self.remove((Bound::Included(value), Bound::Included(value)))
}
#[inline]
pub fn difference(&mut self, other: &Self) -> Result<(), IntervalSetError> {
if self.intervals.is_empty() {
return Ok(());
}
self.set_operation(other, remove)
}
#[inline]
pub fn intersection(&mut self, other: &Self) -> Result<(), IntervalSetError> {
intersection::apply(&mut self.intervals, &other.intervals);
Ok(())
}
#[inline]
pub fn intersection_iter<'a>(&'a self, other: &'a Self) -> Intersection<'a, T> {
Intersection::new(&self.intervals, &other.intervals)
}
#[inline]
pub fn iter(&self) -> Iter<'_, T> {
Iter {
iter: self.intervals.iter(),
head: None,
tail: None,
}
}
#[inline]
pub fn min_value(&self) -> Option<T> {
let interval = self.intervals.front()?;
Some(interval.start)
}
#[inline]
pub fn max_value(&self) -> Option<T> {
let interval = self.intervals.back()?;
Some(interval.end)
}
#[inline]
pub fn contains(&self, value: &T) -> bool {
self.binary_search_with(value, |_index| true, |_index| false, |_index| false)
}
#[inline]
fn set_operation<
F: Fn(
&mut VecDeque<Interval<T>>,
Interval<T>,
usize,
Option<NonZeroUsize>,
) -> Result<usize, IntervalSetError>,
>(
&mut self,
other: &Self,
apply: F,
) -> Result<(), IntervalSetError> {
let mut iter = other.intervals.iter();
let limit = self.limit;
let interval = if let Some(interval) = iter.next() {
interval
} else {
return Ok(());
};
let mut index = self.index_for(interval);
index = apply(&mut self.intervals, *interval, index, limit)?;
for interval in iter {
index = apply(&mut self.intervals, *interval, index, limit)?;
}
self.check_integrity();
Ok(())
}
#[inline]
fn index_for(&self, interval: &Interval<T>) -> usize {
if self.interval_len() < 16 {
return 0;
}
self.binary_search_with(&interval.start, |index| index, |index| index, |index| index)
}
#[inline]
fn binary_search_with<
V,
EqualFn: Fn(usize) -> V,
GreaterFn: Fn(usize) -> V,
LessFn: Fn(usize) -> V,
>(
&self,
value: &T,
on_equal: EqualFn,
on_greater: GreaterFn,
on_less: LessFn,
) -> V {
use core::cmp::Ordering::*;
let intervals = &self.intervals;
let mut size = intervals.len();
if size == 0 {
return on_greater(0);
}
let mut base = 0usize;
while size > 1 {
let half = size / 2;
let mid = base + half;
let subject = &intervals[mid];
match subject.partial_cmp(value) {
Some(Equal) => return on_equal(mid),
Some(Greater) => {}
Some(Less) => base = mid,
None => return on_greater(0),
};
size -= half;
}
let subject = &intervals[base];
match subject.partial_cmp(value) {
Some(Equal) => on_equal(base),
Some(Greater) => on_greater(base),
Some(Less) => on_less(base),
None => on_greater(0),
}
}
#[inline]
fn check_integrity(&self) {
if cfg!(test) {
let mut prev_end: Option<T> = None;
for interval in self.intervals.iter() {
for value in (*interval).take(3) {
assert!(self.contains(&value), "set should contain value");
}
for value in (*interval).rev().take(3) {
assert!(self.contains(&value), "set should contain value");
}
if let Some(prev_end) = prev_end.as_ref() {
assert!(
*prev_end < interval.start_exclusive(),
"the previous end should be less than the next start",
);
}
assert!(interval.is_valid(), "interval should be valid");
prev_end = Some(interval.end);
}
}
}
}
impl<T: Copy> IntervalSet<T> {
#[inline]
pub fn intervals(&self) -> IntervalIter<'_, T> {
IntervalIter {
iter: self.intervals.iter(),
}
}
#[inline]
pub fn ranges(&self) -> RangeIter<'_, T> {
RangeIter {
iter: self.intervals.iter(),
}
}
#[inline]
pub fn inclusive_ranges(&self) -> RangeInclusiveIter<'_, T> {
RangeInclusiveIter {
iter: self.intervals.iter(),
}
}
}
impl<T: Copy + fmt::Debug> fmt::Debug for IntervalSet<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_set().entries(self.intervals.iter()).finish()
}
}
pub struct Iter<'a, T> {
iter: vec_deque::Iter<'a, Interval<T>>,
head: Option<Interval<T>>,
tail: Option<Interval<T>>,
}
impl<T: IntervalBound> Iterator for Iter<'_, T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
loop {
if let Some(item) = self.head.as_mut().and_then(Iterator::next) {
return Some(item);
}
let item = self.iter.next().cloned().or_else(|| self.tail.take())?;
self.head = Some(item);
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (lower, _) = self.iter.size_hint();
let upper = None;
(lower, upper)
}
}
impl<T: IntervalBound> DoubleEndedIterator for Iter<'_, T> {
#[inline]
fn next_back(&mut self) -> Option<T> {
loop {
if let Some(item) = self.tail.as_mut().and_then(DoubleEndedIterator::next_back) {
return Some(item);
}
let item = self
.iter
.next_back()
.cloned()
.or_else(|| self.head.take())?;
self.tail = Some(item);
}
}
}
macro_rules! impl_iterator_conversions {
($item:ident, $iter:ident) => {
#[derive(Clone, Debug)]
pub struct $iter<'a, T> {
iter: vec_deque::Iter<'a, Interval<T>>,
}
impl<'a, T: IntervalBound> Iterator for $iter<'a, T> {
type Item = $item<T>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|interval| interval.into())
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, T: IntervalBound> DoubleEndedIterator for $iter<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(|interval| interval.into())
}
}
impl<'a, T: IntervalBound> ExactSizeIterator for $iter<'a, T> where
vec_deque::Iter<'a, Interval<T>>: ExactSizeIterator
{
}
impl<T: IntervalBound> FromIterator<$item<T>> for IntervalSet<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = $item<T>>>(intervals: I) -> Self {
let intervals = intervals.into_iter();
let mut set = Self::with_capacity(intervals.size_hint().0);
set.extend(intervals);
set
}
}
impl<'a, T: 'a + IntervalBound> FromIterator<&'a $item<T>> for IntervalSet<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = &'a $item<T>>>(intervals: I) -> Self {
let intervals = intervals.into_iter();
let mut set = Self::with_capacity(intervals.size_hint().0);
set.extend(intervals);
set
}
}
impl<T: IntervalBound> Extend<$item<T>> for IntervalSet<T> {
#[inline]
fn extend<I: IntoIterator<Item = $item<T>>>(&mut self, intervals: I) {
for interval in intervals {
if self.insert(interval).is_err() {
return;
}
}
}
}
impl<'a, T: 'a + IntervalBound> Extend<&'a $item<T>> for IntervalSet<T> {
#[inline]
fn extend<I: IntoIterator<Item = &'a $item<T>>>(&mut self, intervals: I) {
for interval in intervals {
let interval: Interval<T> = interval.into();
if self.insert(interval).is_err() {
return;
}
}
}
}
impl<T: IntervalBound> From<$item<T>> for IntervalSet<T> {
#[inline]
fn from(interval: $item<T>) -> Self {
let mut set = Self::with_capacity(1);
let _ = set.insert(interval);
set
}
}
};
}
impl_iterator_conversions!(Interval, IntervalIter);
impl_iterator_conversions!(Range, RangeIter);
impl_iterator_conversions!(RangeInclusive, RangeInclusiveIter);
impl<T: IntervalBound> FromIterator<T> for IntervalSet<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
let values = values.into_iter();
let mut set = Self::with_capacity(values.size_hint().0);
for value in values {
if set.insert_value(value).is_err() {
break;
}
}
set
}
}
impl<'a, T: 'a + IntervalBound> FromIterator<&'a T> for IntervalSet<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = &'a T>>(values: I) -> Self {
values.into_iter().cloned().collect()
}
}