use core::iter::FusedIterator;
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)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
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 {
write!(fmt, "{:?}..{:?}", self.start, self.end)
}
}
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)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
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 {
write!(fmt, "{:?}..", self.start)
}
}
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> From<core::ops::RangeFrom<I>> for TypedRangeFrom<I> {
fn from(value: core::ops::RangeFrom<I>) -> Self {
Self::from_raw(value)
}
}
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 = TypedRangeInclusiveIter<I>;
#[inline]
fn iter(self) -> Self::Iter {
TypedRangeInclusive::from_raw(self).iter()
}
}
#[derive(Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TypedRangeInclusive<I: IndexType> {
pub start: I,
pub end: I,
}
impl<I: IndexType + core::fmt::Debug> core::fmt::Debug for TypedRangeInclusive<I> {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(fmt, "{:?}..={:?}", self.start, self.end)
}
}
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(range: core::ops::RangeInclusive<I>) -> Self {
Self {
start: *range.start(),
end: *range.end(),
}
}
#[inline]
pub const fn iter(self) -> TypedRangeInclusiveIter<I> {
TypedRangeInclusiveIter {
start: self.start,
end: self.end,
exhausted: false,
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.start > self.end
}
#[inline]
pub fn try_len(&self) -> Option<usize> {
let Some(diff) = self.end.checked_sub_index(self.start) else {
return Some(0);
};
diff.to_usize().checked_add(1)
}
#[inline]
pub fn len(&self) -> usize {
self.try_len()
.expect("inclusive range length overflowed usize")
}
}
impl<I: IndexType> From<core::ops::RangeInclusive<I>> for TypedRangeInclusive<I> {
fn from(value: core::ops::RangeInclusive<I>) -> Self {
Self::from_raw(value)
}
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct TypedRangeInclusiveIter<I: IndexType> {
start: I,
end: I,
exhausted: bool,
}
impl<I: IndexType + core::fmt::Debug> core::fmt::Debug for TypedRangeInclusiveIter<I> {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(fmt, "{:?}..={:?}", self.start, self.end)?;
if self.exhausted {
write!(fmt, " (exhausted)")?;
}
Ok(())
}
}
impl<I: IndexType> TypedRangeInclusiveIter<I> {
#[inline]
pub const fn start(&self) -> I {
self.start
}
#[inline]
pub const fn end(&self) -> I {
self.end
}
#[inline]
pub fn is_empty(&self) -> bool {
self.exhausted || self.start > self.end
}
#[inline]
pub fn try_len(&self) -> Option<usize> {
if self.exhausted {
return Some(0);
}
let Some(diff) = self.end.checked_sub_index(self.start) else {
return Some(0);
};
diff.to_usize().checked_add(1)
}
#[inline]
pub fn len(&self) -> usize {
self.try_len()
.expect("inclusive range length overflowed usize")
}
}
impl<I: IndexType> Iterator for TypedRangeInclusiveIter<I> {
type Item = I;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if TypedRangeInclusiveIter::is_empty(self) {
return None;
}
let res = self.start;
match self.start.checked_add_scalar(I::Scalar::ONE) {
Ok(start_plus_1) => self.start = start_plus_1,
Err(_) => self.exhausted = true,
}
Some(res)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self.try_len() {
Some(len) => (len, Some(len)),
None => {
(usize::MAX, None)
}
}
}
#[inline]
fn count(self) -> usize {
self.len()
}
#[inline]
fn nth(&mut self, n: usize) -> Option<I> {
if TypedRangeInclusiveIter::is_empty(self) {
return None;
}
let Some(offset) = I::Scalar::try_from_usize(n) else {
self.exhausted = true;
return None;
};
let Ok(res) = self.start.checked_add_scalar(offset) else {
self.exhausted = true;
return None;
};
if res > self.end {
self.exhausted = true;
return None;
}
match res.checked_add_scalar(I::Scalar::ONE) {
Ok(res_plus_1) => {
self.start = res_plus_1;
}
Err(_) => {
self.exhausted = true;
}
}
Some(res)
}
#[inline]
fn last(mut self) -> Option<Self::Item> {
self.next_back()
}
#[inline]
fn min(mut self) -> Option<Self::Item>
where
I: Ord,
{
self.next()
}
#[inline]
fn max(mut self) -> Option<Self::Item>
where
I: Ord,
{
self.next_back()
}
#[inline]
fn is_sorted(self) -> bool {
true
}
}
impl<I: IndexType> DoubleEndedIterator for TypedRangeInclusiveIter<I> {
#[inline]
fn next_back(&mut self) -> Option<I> {
if TypedRangeInclusiveIter::is_empty(self) {
return None;
}
let res = self.end;
match self.end.checked_sub_scalar(I::Scalar::ONE) {
Some(end_minus_1) => {
self.end = end_minus_1;
}
None => {
self.exhausted = true;
}
};
Some(res)
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<I> {
if TypedRangeInclusiveIter::is_empty(self) {
return None;
}
let Some(offset) = I::Scalar::try_from_usize(n) else {
self.exhausted = true;
return None;
};
let Some(res) = self.end.checked_sub_scalar(offset) else {
self.exhausted = true;
return None;
};
if res < self.start {
self.exhausted = true;
return None;
}
match res.checked_sub_scalar(I::Scalar::ONE) {
Some(res_minus_1) => {
self.end = res_minus_1;
}
None => {
self.exhausted = true;
}
}
Some(res)
}
}
impl<I: IndexType> ExactSizeIterator for TypedRangeInclusiveIter<I> {
#[inline]
fn len(&self) -> usize {
TypedRangeInclusiveIter::len(self)
}
}
impl<I: IndexType> FusedIterator for TypedRangeInclusiveIter<I> {}