use core::{hint::unreachable_unchecked, iter::FusedIterator, ops::RangeBounds};
use crate::{IndexScalarType, IndexType};
pub trait TypedRangeIterExt<I: IndexType> {
type Iter: Iterator<Item = I>;
fn iter(self) -> Self::Iter;
}
impl<I: IndexType> TypedRangeIterExt<I> for core::ops::Range<I> {
type Iter = TypedRange<I>;
#[inline]
fn iter(self) -> Self::Iter {
TypedRange::from_raw(self)
}
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct TypedRange<I: IndexType> {
pub start: I,
pub end: I,
}
impl<I: IndexType + core::fmt::Debug> core::fmt::Debug for TypedRange<I> {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.start.fmt(fmt)?;
write!(fmt, "..")?;
self.end.fmt(fmt)?;
Ok(())
}
}
impl<I: IndexType> TypedRange<I> {
#[inline]
pub const fn into_raw(self) -> core::ops::Range<I> {
self.start..self.end
}
#[inline]
pub const fn from_raw(value: core::ops::Range<I>) -> Self {
Self {
start: value.start,
end: value.end,
}
}
#[inline]
pub fn len(&self) -> usize {
self.end
.checked_sub_index(self.start)
.unwrap_or(I::Scalar::ZERO)
.to_usize()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.start >= self.end
}
}
impl<I: IndexType> From<core::ops::Range<I>> for TypedRange<I> {
fn from(value: core::ops::Range<I>) -> Self {
Self::from_raw(value)
}
}
impl<I: IndexType> Iterator for TypedRange<I> {
type Item = I;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.start >= self.end {
return None;
}
let res = self.start;
self.start = unsafe { res.unchecked_add_scalar(I::Scalar::ONE) };
Some(res)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
#[inline]
fn count(self) -> usize {
self.len()
}
#[inline]
fn nth(&mut self, n: usize) -> Option<I> {
let Some(offset) = I::Scalar::try_from_usize(n) else {
self.start = self.end;
return None;
};
let Ok(res) = self.start.checked_add_scalar(offset) else {
self.start = self.end;
return None;
};
if res >= self.end {
self.start = self.end;
return None;
}
self.start = unsafe { res.unchecked_add_scalar(I::Scalar::ONE) };
Some(res)
}
#[inline]
fn last(mut self) -> Option<I> {
self.next_back()
}
#[inline]
fn min(mut self) -> Option<I>
where
I: Ord,
{
self.next()
}
#[inline]
fn max(mut self) -> Option<I>
where
I: Ord,
{
self.next_back()
}
#[inline]
fn is_sorted(self) -> bool {
true
}
}
impl<I: IndexType> DoubleEndedIterator for TypedRange<I> {
#[inline]
fn next_back(&mut self) -> Option<I> {
if self.start >= self.end {
return None;
}
let res = unsafe { self.end.unchecked_sub_scalar(I::Scalar::ONE) };
self.end = res;
Some(res)
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<I> {
let Some(offset) = I::Scalar::try_from_usize(n) else {
self.end = self.start;
return None;
};
let Some(res) = self
.end
.checked_sub_scalar(offset)
.and_then(|x| x.checked_sub_scalar(I::Scalar::ONE))
else {
self.end = self.start;
return None;
};
if res < self.start {
self.end = self.start;
return None;
}
self.end = res;
Some(res)
}
}
impl<I: IndexType> ExactSizeIterator for TypedRange<I> {
#[inline]
fn len(&self) -> usize {
self.len()
}
}
impl<I: IndexType> FusedIterator for TypedRange<I> {}
impl<I: IndexType> TypedRangeIterExt<I> for core::ops::RangeFrom<I> {
type Iter = TypedRangeFrom<I>;
#[inline]
fn iter(self) -> Self::Iter {
TypedRangeFrom::from_raw(self)
}
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct TypedRangeFrom<I: IndexType> {
pub start: I,
}
impl<I: IndexType + core::fmt::Debug> core::fmt::Debug for TypedRangeFrom<I> {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.start.fmt(fmt)?;
write!(fmt, "..")?;
Ok(())
}
}
impl<I: IndexType> TypedRangeFrom<I> {
#[inline]
pub const fn into_raw(self) -> core::ops::RangeFrom<I> {
self.start..
}
pub const fn from_raw(value: core::ops::RangeFrom<I>) -> Self {
Self { start: value.start }
}
}
impl<I: IndexType> Iterator for TypedRangeFrom<I> {
type Item = I;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let res = self.start;
self.start = res.checked_add_scalar(I::Scalar::ONE).unwrap();
Some(res)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(usize::MAX, None)
}
#[inline]
fn nth(&mut self, n: usize) -> Option<I> {
let res = self
.start
.checked_add_scalar(I::Scalar::try_from_usize(n).unwrap())
.unwrap();
self.start = res.checked_add_scalar(I::Scalar::ONE).unwrap();
Some(res)
}
#[inline]
fn min(mut self) -> Option<I>
where
I: Ord,
{
self.next()
}
#[inline]
fn is_sorted(self) -> bool {
true
}
}
impl<I: IndexType> FusedIterator for TypedRangeFrom<I> {}
impl<I: IndexType> TypedRangeIterExt<I> for core::ops::RangeInclusive<I> {
type Iter = TypedRangeInclusive<I>;
#[inline]
fn iter(self) -> Self::Iter {
TypedRangeInclusive::from_raw_lossy(self)
}
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct TypedRangeInclusive<I: IndexType> {
start: I,
end: I,
exhausted: bool,
}
impl<I: IndexType + core::fmt::Debug> core::fmt::Debug for TypedRangeInclusive<I> {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.start.fmt(fmt)?;
write!(fmt, "..=")?;
self.end.fmt(fmt)?;
if self.exhausted {
write!(fmt, " (exhausted)")?;
}
Ok(())
}
}
impl<I: IndexType> TypedRangeInclusive<I> {
#[inline]
pub const fn into_raw(self) -> core::ops::RangeInclusive<I> {
self.start..=self.end
}
#[inline]
pub const fn from_raw_lossy(range: core::ops::RangeInclusive<I>) -> Self {
let start = *range.start();
let end = *range.end();
Self {
start,
end,
exhausted: false,
}
}
pub fn from_raw(range: core::ops::RangeInclusive<I>) -> Self {
match range.end_bound() {
core::ops::Bound::Excluded(i) => Self {
start: *range.start(),
end: *i,
exhausted: true,
},
core::ops::Bound::Included(i) => {
let start = *range.start();
let end = *i;
Self {
start,
end,
exhausted: false,
}
}
core::ops::Bound::Unbounded => unsafe { unreachable_unchecked() },
}
}
#[inline]
pub fn start(&self) -> I {
self.start
}
#[inline]
pub fn end(&self) -> I {
self.end
}
fn exhasut_from_start(&mut self) {
self.start = self.end;
self.exhausted = true;
}
fn exhasut_from_end(&mut self) {
self.end = self.start;
self.exhausted = true;
}
#[inline]
pub fn is_empty(&self) -> bool {
self.exhausted || (self.start > self.end)
}
#[inline]
pub fn len(&self) -> usize {
if self.exhausted {
return 0;
}
let Some(diff) = self.end.checked_sub_index(self.start) else {
return 0;
};
unsafe { diff.unchecked_add_scalar(I::Scalar::ONE) }.to_usize()
}
}
impl<I: IndexType> Iterator for TypedRangeInclusive<I> {
type Item = I;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if TypedRangeInclusive::is_empty(self) {
return None;
}
if self.start == self.end {
self.exhausted = true;
Some(self.start)
} else {
let res = self.start;
self.start = unsafe { res.unchecked_add_scalar(I::Scalar::ONE) };
Some(res)
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
#[inline]
fn count(self) -> usize {
self.len()
}
#[inline]
fn nth(&mut self, n: usize) -> Option<I> {
if TypedRangeInclusive::is_empty(self) {
return None;
}
let Some(offset) = I::Scalar::try_from_usize(n) else {
self.exhasut_from_start();
return None;
};
let Ok(res) = self.start.checked_add_scalar(offset) else {
self.exhasut_from_start();
return None;
};
if res > self.end {
self.exhasut_from_start();
None
} else if res == self.end {
self.exhasut_from_start();
Some(res)
} else {
self.start = unsafe { res.unchecked_add_scalar(I::Scalar::ONE) };
Some(res)
}
}
#[inline]
fn last(mut self) -> Option<I> {
self.next_back()
}
#[inline]
fn min(mut self) -> Option<I>
where
I: Ord,
{
self.next()
}
#[inline]
fn max(mut self) -> Option<I>
where
I: Ord,
{
self.next_back()
}
#[inline]
fn is_sorted(self) -> bool {
true
}
}
impl<I: IndexType> DoubleEndedIterator for TypedRangeInclusive<I> {
#[inline]
fn next_back(&mut self) -> Option<I> {
if TypedRangeInclusive::is_empty(self) {
return None;
}
if self.end == self.start {
self.exhausted = true;
Some(self.end)
} else {
let res = self.end;
self.end = unsafe { res.unchecked_sub_scalar(I::Scalar::ONE) };
Some(res)
}
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<I> {
if TypedRangeInclusive::is_empty(self) {
return None;
}
let Some(offset) = I::Scalar::try_from_usize(n) else {
self.exhasut_from_end();
return None;
};
let Some(res) = self.end.checked_sub_scalar(offset) else {
self.exhasut_from_end();
return None;
};
if res < self.start {
self.exhasut_from_end();
None
} else if res == self.start {
self.exhasut_from_end();
Some(res)
} else {
self.end = unsafe { res.unchecked_sub_scalar(I::Scalar::ONE) };
Some(res)
}
}
}
impl<I: IndexType> ExactSizeIterator for TypedRangeInclusive<I> {
fn len(&self) -> usize {
self.len()
}
}
impl<I: IndexType> FusedIterator for TypedRangeInclusive<I> {}