use core::iter::FusedIterator;
use core::mem::MaybeUninit;
use core::ptr::drop_in_place;
use core::slice;
use nvec::n_vec::NVec;
#[must_use]
pub struct IntoIter<T, const N: usize> {
position: usize,
remaining: usize,
data: [MaybeUninit<T>; N],
}
impl<T, const N: usize> IntoIter<T, N> {
#[inline]
pub(super) fn new(v: NVec<T, N>) -> Self {
let (data, remaining) = v.into_raw_parts();
Self { position: 0, remaining, data }
}
#[inline]
#[must_use]
pub fn as_slice(&self) -> &[T] {
let len = self.remaining;
let data = {
let base = self.data.as_ptr().cast::<T>();
unsafe { base.add(self.position) }
};
unsafe { slice::from_raw_parts(data, len) }
}
#[inline]
#[must_use]
pub fn as_mut_slice(&mut self) -> &mut [T] {
let len = self.remaining;
let data = {
let base = self.data.as_mut_ptr().cast::<T>();
unsafe { base.add(self.position) }
};
unsafe { slice::from_raw_parts_mut(data, len) }
}
}
impl<T, const N: usize> Default for IntoIter<T, N> {
#[inline]
fn default() -> Self {
Self::new(Default::default())
}
}
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
fn next_back(&mut self) -> Option<Self::Item> {
let slot: *const T = self.as_slice().last()?;
let value = unsafe { slot.read() };
self.remaining -= 1;
Some(value)
}
}
impl<T, const N: usize> Drop for IntoIter<T, N> {
fn drop(&mut self) {
let to_drop = self.as_mut_slice();
unsafe { drop_in_place(to_drop) };
}
}
impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {}
impl<T, const N: usize> Iterator for IntoIter<T, N> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let slot: *const T = self.as_slice().first()?;
let value = unsafe { slot.read() };
self.position += 1;
self.remaining -= 1;
Some(value)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.remaining;
(size, Some(size))
}
}