use core::mem;
use core::ptr;
use core::ptr::NonNull;
use core::slice;
use core::iter::FusedIterator;
pub struct Drain<'a, T: 'a, const N: usize> {
pub(super) tail_start: usize,
pub(super) tail_len: usize,
pub(super) iter: slice::Iter<'a, T>,
pub(super) arr: NonNull<super::Array<T, N>>,
}
impl<'a, T, const N: usize> Drain<'a, T, N> {
#[must_use]
pub fn as_slice(&self) -> &[T] {
self.iter.as_slice()
}
}
unsafe impl<T: Sync, const N: usize> Sync for Drain<'_, T, N> {}
unsafe impl<T: Send, const N: usize> Send for Drain<'_, T, N> {}
impl<T, const N: usize> Iterator for Drain<'_, T, N> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
self.iter
.next()
.map(|elt| unsafe { ptr::read(elt as *const _) })
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<T, const N: usize> DoubleEndedIterator for Drain<'_, T, N> {
#[inline]
fn next_back(&mut self) -> Option<T> {
self.iter
.next_back()
.map(|elt| unsafe { ptr::read(elt as *const _) })
}
}
impl<T, const N: usize> Drop for Drain<'_, T, N> {
fn drop(&mut self) {
struct DropGuard<'r, 'a, T, const N: usize>(&'r mut Drain<'a, T, N>);
impl<'r, 'a, T, const N: usize> Drop for DropGuard<'r, 'a, T, N> {
fn drop(&mut self) {
if self.0.tail_len > 0 {
unsafe {
let source_vec = self.0.arr.as_mut();
let start = source_vec.len();
let tail = self.0.tail_start;
if tail != start {
let src = source_vec.as_ptr().add(tail);
let dst = source_vec.as_mut_ptr().add(start);
ptr::copy(src, dst, self.0.tail_len);
}
source_vec.set_len(start + self.0.tail_len);
}
}
}
}
let iter = mem::replace(&mut self.iter, (&mut []).iter());
let drop_len = iter.len();
let mut vec = self.arr;
if mem::size_of::<T>() == 0 {
unsafe {
let vec = vec.as_mut();
let old_len = vec.len();
vec.set_len(old_len + drop_len + self.tail_len);
vec.truncate(old_len + self.tail_len);
}
return;
}
let _guard = DropGuard(self);
if drop_len == 0 {
return;
}
let drop_ptr = iter.as_slice().as_ptr();
unsafe {
let vec_ptr = vec.as_mut().as_mut_ptr();
let drop_offset = drop_ptr.offset_from(vec_ptr) as usize;
let to_drop = ptr::slice_from_raw_parts_mut(vec_ptr.add(drop_offset), drop_len);
ptr::drop_in_place(to_drop);
}
}
}
impl<T, const N: usize> ExactSizeIterator for Drain<'_, T, N> {}
impl<T, const N: usize> FusedIterator for Drain<'_, T, N> {}