macro_rules! gen_vector_iter_impl {
($($life:lifetime, )? $name:ident, $type:ty, $item:ty, $get_unchecked:ident, $get:ident) => {
impl $(<$life>)? $name $(<$life>)? {
#[must_use]
fn new(vec: $(&$life)? $type) -> Self {
if vec.is_empty() {
return Self {
vec,
index: 0,
back_index: None,
};
}
let last = vec.len() - 1;
Self {
vec,
index: 0,
back_index: Some(last),
}
}
fn advance_by(&mut self, n: usize) -> Result<(), std::num::NonZeroUsize> {
if n == 0 {
return Ok(());
}
if Some(self.index + n - 1) > self.back_index {
if Some(self.index) > self.back_index {
Err(std::num::NonZeroUsize::new(n).unwrap())
} else {
Err(std::num::NonZeroUsize::new(n - (self.back_index.as_ref().unwrap_or(&usize::MAX).wrapping_sub(self.index).wrapping_add(1))).unwrap())
}
} else {
self.index += n;
Ok(())
}
}
fn advance_back_by(&mut self, n: usize) -> Result<(), std::num::NonZeroUsize> {
if n == 0 {
return Ok(());
}
if self.is_iter_empty() {
return Err(std::num::NonZeroUsize::new(n).unwrap());
}
let remaining = *self.back_index.as_ref().unwrap() - self.index + 1;
if remaining < n {
return Err(std::num::NonZeroUsize::new(n - remaining).unwrap());
}
self.back_index = if self.back_index >= Some(n) { self.back_index.map(|b| b - n) } else { None };
Ok(())
}
fn is_iter_empty(&self) -> bool {
Some(self.index) > self.back_index
}
}
impl $(<$life>)? Iterator for $name $(<$life>)? {
type Item = $item;
fn next(&mut self) -> Option<Self::Item> {
if self.is_iter_empty() {
return None;
}
self.vec.$get(self.index).map(|v| {
self.index += 1;
v
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), Some(self.len()))
}
fn count(self) -> usize
where
Self: Sized,
{
self.len()
}
fn last(self) -> Option<Self::Item>
where
Self: Sized,
{
if self.is_iter_empty() {
return None;
}
Some(self.vec.$get_unchecked(*self.back_index.as_ref().unwrap()))
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.advance_by(n).ok()?;
self.next()
}
}
impl $(<$life>)? std::iter::ExactSizeIterator for $name $(<$life>)? {
fn len(&self) -> usize {
(*self.back_index.as_ref().unwrap_or(&usize::MAX)).wrapping_sub(self.index).wrapping_add(1)
}
}
impl $(<$life>)? std::iter::FusedIterator for $name $(<$life>)? {}
impl $(<$life>)? std::iter::DoubleEndedIterator for $name $(<$life>)? {
fn next_back(&mut self) -> Option<Self::Item> {
if Some(self.index) > self.back_index {
return None;
}
self.vec.$get(*self.back_index.as_ref().unwrap()).map(|v| {
if *self.back_index.as_ref().unwrap() == 0 {
self.back_index = None;
} else {
self.back_index = Some(self.back_index.unwrap() - 1);
}
v
})
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.advance_back_by(n).ok()?;
self.next_back()
}
}
};
}
macro_rules! impl_into_iterator_impls {
($type:ty, $own:ident, $bor:ident) => {
crate::util::impl_into_iterator_impls! { $type, $own, $bor, u64 }
};
($type:ty, $own:ident, $bor:ident, $element_type:ty) => {
impl IntoIterator for $type {
type Item = $element_type;
type IntoIter = $own;
fn into_iter(self) -> Self::IntoIter {
$own::new(self)
}
}
impl<'a> IntoIterator for &'a $type {
type Item = $element_type;
type IntoIter = $bor<'a>;
fn into_iter(self) -> Self::IntoIter {
$bor::new(self)
}
}
#[allow(clippy::into_iter_without_iter)]
impl<'a> IntoIterator for &'a mut $type {
type Item = $element_type;
type IntoIter = $bor<'a>;
fn into_iter(self) -> Self::IntoIter {
$bor::new(self)
}
}
};
}
macro_rules! impl_vector_iterator {
($type:ty, $own:ident, $bor:ident) => { impl_vector_iterator! { $type, $own, $bor, get_unchecked, get, u64 } };
($type:ty, $own:ident, $bor:ident, $get_unchecked:ident, $get:ident, $return_type:ty, special) => {
#[doc = concat!("An owning iterator for `", stringify!($type), "`.")]
#[derive(Clone, Debug)]
pub struct $own {
vec: $type,
index: usize,
back_index: Option<usize>,
}
#[doc = concat!("A borrowing iterator for `", stringify!($type), "`.")]
#[derive(Clone, Debug)]
pub struct $bor<'a> {
vec: &'a $type,
index: usize,
back_index: Option<usize>,
}
crate::util::gen_vector_iter_impl!($own, $type, $return_type, $get_unchecked, $get);
crate::util::gen_vector_iter_impl!('a, $bor, $type, $return_type, $get_unchecked, $get);
};
($type:ty, $own:ident, $bor:ident, $get_unchecked:ident, $get:ident, $return_type:ty) => {
impl_vector_iterator! { $type, $own, $bor, $get_unchecked, $get, $return_type, special }
impl $type {
#[doc = concat!("Returns an iterator over the elements of `", stringify!($type), "`.")]
#[doc = concat!("The iterator returns `", stringify!($return_type), "` elements.")]
#[must_use]
pub fn iter(&self) -> $bor<'_> {
$bor::new(self)
}
}
crate::util::impl_into_iterator_impls!($type, $own, $bor, $return_type);
}
}
pub(crate) use gen_vector_iter_impl;
pub(crate) use impl_into_iterator_impls;
pub(crate) use impl_vector_iterator;