use crate::{Bound, LowerBound, Rangetools, Step, UpperBound};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::iter::FusedIterator;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct BoundedRange<T> {
pub start: LowerBound<T>,
pub end: UpperBound<T>,
}
impl<T> From<std::ops::Range<T>> for BoundedRange<T> {
fn from(r: std::ops::Range<T>) -> Self {
Self {
start: LowerBound::included(r.start),
end: UpperBound::excluded(r.end),
}
}
}
impl<T> From<std::ops::RangeInclusive<T>> for BoundedRange<T> {
fn from(r: std::ops::RangeInclusive<T>) -> Self {
let (start, end) = r.into_inner();
Self {
start: LowerBound::included(start),
end: UpperBound::included(end),
}
}
}
impl<T> From<BoundedRange<T>> for std::ops::Range<T>
where
T: Copy + Step,
{
fn from(r: BoundedRange<T>) -> Self {
let start = match r.start.to_bound() {
Bound::Excluded(t) => Step::forward(t, 1),
Bound::Included(t) => t,
};
let end = match r.end.to_bound() {
Bound::Excluded(t) => t,
Bound::Included(t) => Step::forward(t, 1),
};
start..end
}
}
impl<T> From<BoundedRange<T>> for std::ops::RangeInclusive<T>
where
T: Copy + Step,
{
fn from(r: BoundedRange<T>) -> Self {
let start = match r.start.to_bound() {
Bound::Excluded(t) => Step::forward(t, 1),
Bound::Included(t) => t,
};
let end = match r.end.to_bound() {
Bound::Excluded(t) => Step::backward(t, 1),
Bound::Included(t) => t,
};
start..=end
}
}
impl<T> IntoIterator for BoundedRange<T>
where
T: Copy + Ord + Step,
{
type IntoIter = BoundedRangeIter<T>;
type Item = T;
fn into_iter(self) -> Self::IntoIter {
let current = match self.start {
LowerBound(Bound::Excluded(t)) => Step::forward(t, 1),
LowerBound(Bound::Included(t)) => t,
};
let last = match self.end {
UpperBound(Bound::Excluded(t)) => Step::backward(t, 1),
UpperBound(Bound::Included(t)) => t,
};
BoundedRangeIter { current, last }
}
}
impl<T: Copy + Ord> BoundedRange<T> {
pub fn new(start: LowerBound<T>, end: UpperBound<T>) -> Self {
Self { start, end }
}
pub fn contains(&self, t: T) -> bool {
let start_satisfied = match self.start.0 {
Bound::Excluded(s) => t > s,
Bound::Included(s) => t >= s,
};
let end_satisfied = match self.end.0 {
Bound::Excluded(e) => t < e,
Bound::Included(e) => t <= e,
};
start_satisfied && end_satisfied
}
pub(crate) fn combine(&self, other: &Self) -> Self {
if other.is_empty() {
return self.clone();
}
if self.is_empty() {
return other.clone();
}
assert!(self.intersects(*other));
BoundedRange::new(
LowerBound::min(self.start, other.start),
UpperBound::max(self.end, other.end),
)
}
}
#[derive(Clone, Debug)]
pub struct BoundedRangeIter<T> {
current: T,
last: T,
}
impl<T> Iterator for BoundedRangeIter<T>
where
T: Copy + Ord + Step,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.current > self.last {
None
} else {
let t = self.current;
self.current = Step::forward(self.current, 1);
Some(t)
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = Step::steps_between(&self.current, &self.last)
.map(|steps| steps + 1)
.unwrap_or_default();
(size, Some(size))
}
fn count(self) -> usize {
self.len()
}
fn last(self) -> Option<Self::Item>
where
Self: Sized,
{
if self.current > self.last {
None
} else {
Some(self.last)
}
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.current = Step::forward(self.current, n);
self.next()
}
fn min(mut self) -> Option<Self::Item> {
self.next()
}
fn max(mut self) -> Option<Self::Item> {
self.next_back()
}
}
impl<T> DoubleEndedIterator for BoundedRangeIter<T>
where
T: Copy + Ord + Step,
{
fn next_back(&mut self) -> Option<Self::Item> {
if self.current > self.last {
None
} else {
let t = self.last;
self.last = Step::backward(self.last, 1);
Some(t)
}
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.last = Step::backward(self.last, n);
self.next_back()
}
}
impl<T> ExactSizeIterator for BoundedRangeIter<T> where T: Copy + Ord + Step {}
impl<T> FusedIterator for BoundedRangeIter<T> where T: Copy + Ord + Step {}