use core::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator};
use core::marker::PhantomData;
use core::ptr::NonNull;
use crate::arr::ArrayElem;
pub struct RegArrayIter<'a, P: ArrayElem<'a>> {
start: NonNull<P::Target>,
end: NonNull<P::Target>,
_phantom: PhantomData<&'a ()>,
}
impl<'a, P: ArrayElem<'a>> Clone for RegArrayIter<'a, P> {
fn clone(&self) -> Self {
RegArrayIter {
start: Clone::clone(&self.start),
end: Clone::clone(&self.end),
_phantom: Clone::clone(&self._phantom),
}
}
}
impl<'a, P: ArrayElem<'a>> RegArrayIter<'a, P> {
pub(crate) const fn new(base: NonNull<[P::Target]>) -> Self {
let start: NonNull<P::Target> = base.cast();
let len = base.len();
let end: NonNull<P::Target> = unsafe { start.add(len) };
Self {
start,
end,
_phantom: PhantomData,
}
}
#[inline(always)]
unsafe fn post_inc_start(&mut self, offset: usize) -> NonNull<P::Target> {
let old = self.start;
unsafe { self.start = self.start.add(offset) };
old
}
#[inline(always)]
unsafe fn pre_dec_end(&mut self, offset: usize) -> NonNull<P::Target> {
unsafe {
self.end = self.end.sub(offset);
self.end
}
}
#[inline]
unsafe fn next_unchecked(&mut self) -> P {
unsafe { P::from_nonnull(self.post_inc_start(1)) }
}
#[inline]
unsafe fn next_back_unchecked(&mut self) -> P {
unsafe { P::from_nonnull(self.pre_dec_end(1)) }
}
}
impl<'a, P: ArrayElem<'a>> Iterator for RegArrayIter<'a, P> {
type Item = P;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
unsafe {
if self.len() == 0 {
None
} else {
Some(self.next_unchecked())
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let exact = self.len();
(exact, Some(exact))
}
#[inline]
fn count(self) -> usize {
self.len()
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
if n >= self.len() {
self.start = self.end;
None
} else {
unsafe {
self.post_inc_start(n);
Some(self.next_unchecked())
}
}
}
#[inline]
fn last(mut self) -> Option<Self::Item> {
self.next_back()
}
}
impl<'a, P: ArrayElem<'a>> ExactSizeIterator for RegArrayIter<'a, P> {
#[inline(always)]
fn len(&self) -> usize {
unsafe { usize::try_from(self.end.offset_from(self.start)).unwrap_unchecked() }
}
}
impl<'a, P: ArrayElem<'a>> DoubleEndedIterator for RegArrayIter<'a, P> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
unsafe {
if self.len() == 0 {
None
} else {
Some(self.next_back_unchecked())
}
}
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
if n >= self.len() {
self.end = self.start;
None
} else {
unsafe {
self.pre_dec_end(n);
Some(self.next_back_unchecked())
}
}
}
}
impl<'a, P: ArrayElem<'a>> FusedIterator for RegArrayIter<'a, P> {}