#[doc = include_str!("../README.md")]
use std::{
marker::PhantomData,
ops::{Bound, RangeBounds},
vec,
};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Ranges<T: Int>(Vec<Range<T>>);
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Range<T: Int>(T, T);
pub trait Int: PartialOrd + Ord + PartialEq + Eq + Copy + Clone {
const MAX: Self;
const MIN: Self;
fn inc(self) -> Self;
fn dec(self) -> Self;
}
macro_rules! impl_int {
($ident:ty) => {
impl Int for $ident {
const MAX : Self = <$ident>::MAX;
const MIN : Self = <$ident>::MIN;
fn inc(self)->Self {
self.saturating_add(1)
}
fn dec(self)->Self {
self.saturating_sub(1)
}
}
};
($($ident:ty),*) => {
$( impl_int!($ident); )*
}
}
impl_int!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize);
impl<T: Int> From<(Bound<T>, Bound<T>)> for Range<T> {
#[inline]
fn from(src: (Bound<T>, Bound<T>)) -> Self {
let start = match src.0 {
Bound::Excluded(i) => i.dec(),
Bound::Included(i) => i,
Bound::Unbounded => T::MIN,
};
let end = match src.1 {
Bound::Excluded(i) => i.inc(),
Bound::Included(i) => i,
Bound::Unbounded => T::MAX,
};
assert!(
start <= end,
"range start has to be less or equal to the end"
);
Range(start, end)
}
}
pub struct Wrap<I: Int, T: RangeBounds<I>>(T, PhantomData<I>);
pub fn wrap<I: Int, T: RangeBounds<I>>(src: T) -> Wrap<I, T> {
Wrap(src, PhantomData)
}
impl<I: Int, T: RangeBounds<I>> From<Wrap<I, T>> for Range<I> {
#[inline]
fn from(src: Wrap<I, T>) -> Self {
let start = match src.0.start_bound() {
Bound::Excluded(i) => i.dec(),
Bound::Included(i) => *i,
Bound::Unbounded => I::MIN,
};
let end = match src.0.end_bound() {
Bound::Excluded(i) => i.inc(),
Bound::Included(i) => *i,
Bound::Unbounded => I::MAX,
};
assert!(
start <= end,
"range start has to be less or equal to the end"
);
Range(start, end)
}
}
impl<T: Int> From<(T, T)> for Range<T> {
#[inline]
fn from(src: (T, T)) -> Self {
let start = src.0;
let end = src.1;
assert!(
start <= end,
"range start has to be less or equal to the end"
);
Range(start, end)
}
}
impl<T: Int> From<Range<T>> for (T, T) {
#[inline]
fn from(val: Range<T>) -> Self {
(val.0, val.1)
}
}
impl<T: Int> From<Ranges<T>> for Vec<(T, T)> {
#[inline]
fn from(val: Ranges<T>) -> Self {
val.0.into_iter().map(|i| i.into()).collect()
}
}
impl<T: Int, U> From<Vec<U>> for Ranges<T>
where
U: Into<Range<T>>,
{
#[inline]
fn from(src: Vec<U>) -> Self {
let mut ranges: Vec<Range<T>> = src.into_iter().map(|u| u.into()).collect();
ranges.sort_by_cached_key(|val| val.0);
let mut result = Vec::new();
for cur in ranges {
if result.is_empty() {
result.push(cur);
continue;
}
let prev = result.last_mut().unwrap();
if prev.1 < (cur.0.dec()) {
result.push(cur);
continue;
}
prev.1 = T::max(prev.1, cur.1);
}
Ranges(result)
}
}
impl<T: Int> Ranges<T> {
#[inline]
pub fn invert(self) -> Self {
let ranges = self.0;
let mut new_ranges = vec![];
if ranges.is_empty() {
return Ranges(vec![Range(T::MIN, T::MAX)]);
}
if ranges[0].0 != T::MIN {
new_ranges.push(Range(T::MIN, ranges[0].0.dec()));
}
for slice in ranges.windows(2) {
new_ranges.push(Range(slice[0].1.inc(), slice[1].0.dec()));
}
let last = ranges.last().unwrap().1;
if last != T::MAX {
new_ranges.push(Range(last.inc(), T::MAX));
}
Ranges(new_ranges)
}
#[inline]
pub fn full() -> Self {
Ranges(vec![Range(T::MIN, T::MAX)])
}
#[inline]
pub fn empty() -> Self {
Ranges(vec![])
}
#[inline]
pub fn union<R: Into<Self>>(mut self, other: R) -> Self {
self.0.append(&mut other.into().0);
Self::from(self.0)
}
#[inline]
pub fn intersect<R: Into<Self>>(&self, other: R) -> Self {
let mut left = self.0.iter();
let other = other.into();
let mut right = other.0.iter();
let mut left_next = left.next();
let mut right_next = right.next();
let mut result = Vec::new();
while let (Some(left_value), Some(right_value)) = (left_next, right_next) {
let start = T::max(left_value.0, right_value.0);
let end;
if left_value.1 < right_value.1 {
end = left_value.1;
left_next = left.next();
} else {
end = right_value.1;
right_next = right.next();
}
if start > end {
continue;
}
let cur = Range(start, end);
if result.is_empty() {
result.push(cur);
continue;
}
let prev = result.last_mut().unwrap();
if prev.1 < (cur.0.dec()) {
result.push(cur);
continue;
}
prev.1 = T::max(prev.1, cur.1);
}
Ranges(result)
}
#[inline]
pub fn contains<R: Into<Self>>(&self, other: R) -> bool {
let mut left = self.0.iter();
let other = other.into();
let mut right = other.0.iter();
let mut left_next = left.next();
let mut right_next = right.next();
while let (Some(left_value), Some(right_value)) = (left_next, right_next) {
let start = T::max(left_value.0, right_value.0);
let end;
if left_value.1 < right_value.1 {
end = left_value.1;
left_next = left.next();
} else {
end = right_value.1;
right_next = right.next();
}
if start > end {
continue;
}
return true;
}
false
}
}