use core::fmt;
use core::fmt::Debug;
use core::iter;
use core::iter::FusedIterator;
use core::mem::MaybeUninit;
use core::ops::Range;
use core::ptr;
use crate::transmute::transmute_unchecked;
pub struct IntoIter<T, const N: usize> {
arr: [MaybeUninit<T>; N],
init: Range<usize>,
}
impl<T, const N: usize> IntoIter<T, N> {
#[inline]
pub fn new(arr: [T; N]) -> Self {
let arr = unsafe { transmute_unchecked(arr) };
let init = 0..N;
Self { arr, init }
}
#[inline]
pub unsafe fn new_unchecked(arr: [MaybeUninit<T>; N], init: Range<usize>) -> Self {
Self { arr, init }
}
#[inline]
pub fn as_slice(&self) -> &[T] {
unsafe {
let slice = self.arr.get_unchecked(self.init.clone());
&*(slice as *const [MaybeUninit<T>] as *const [T])
}
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe {
let slice = self.arr.get_unchecked_mut(self.init.clone());
&mut *(slice as *mut [MaybeUninit<T>] as *mut [T])
}
}
}
impl<T, const N: usize> Debug for IntoIter<T, N>
where
T: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
}
}
impl<T, const N: usize> Clone for IntoIter<T, N>
where
T: Clone,
{
#[inline]
fn clone(&self) -> Self {
let mut new = Self {
arr: unsafe { MaybeUninit::uninit().assume_init() },
init: 0..0,
};
for (src, dst) in iter::zip(self.as_slice(), &mut new.arr) {
dst.write(src.clone());
new.init.end += 1;
}
new
}
}
impl<T, const N: usize> Drop for IntoIter<T, N> {
#[inline]
fn drop(&mut self) {
let slice = self.as_mut_slice();
unsafe { ptr::drop_in_place(slice) }
}
}
impl<T, const N: usize> Iterator for IntoIter<T, N> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.init.next().map(|i| {
unsafe { self.arr.get_unchecked(i).assume_init_read() }
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.init.len();
(len, Some(len))
}
#[inline]
fn count(self) -> usize {
self.init.len()
}
}
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
#[inline]
fn len(&self) -> usize {
self.init.len()
}
}
impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}