use crate::TinyVec;
use core::iter::FusedIterator;
use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop};
use core::ptr::{self, NonNull};
use core::slice;
pub struct Drain<'a, T: 'a, const N: usize> {
pub (super) remaining_start: usize,
pub (super) remaining_len: usize,
pub (super) tail_start: usize,
pub (super) tail_len: usize,
pub (super) vec: NonNull<TinyVec<T, N>>,
pub (super) _marker: PhantomData<&'a mut TinyVec<T, N>>,
}
impl<'a, T: 'a, const N: usize> Drain<'a, T, N> {
#[inline]
pub fn as_slice(&self) -> &[T] {
unsafe {
let ptr = self.vec.as_ref().as_ptr().add(self.remaining_start);
slice::from_raw_parts(ptr, self.remaining_len)
}
}
pub fn keep_rest(self) {
let mut slf = ManuallyDrop::new(self);
unsafe {
let vec = slf.vec.as_mut();
let start = vec.len();
if mem::size_of::<T>() != 0 {
let buf = vec.as_mut_ptr();
let start_ptr = buf.add(start);
let remaining_ptr = buf.add(slf.remaining_start);
if remaining_ptr != start_ptr {
ptr::copy(remaining_ptr, start_ptr, slf.remaining_len);
}
if slf.tail_start != (start + slf.remaining_len) {
let src = buf.add(slf.tail_start);
let dst = start_ptr.add(slf.remaining_len);
ptr::copy(src, dst, slf.tail_len);
}
}
vec.set_len(start + slf.remaining_len + slf.tail_len);
}
}
}
impl<'a, T: 'a, const N: usize> Iterator for Drain<'a, T, N> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.remaining_len == 0 {
None
} else {
unsafe {
let e = self.vec.as_ref().as_ptr().add(self.remaining_start).read();
self.remaining_start += 1;
self.remaining_len -= 1;
Some(e)
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining_len, Some(self.remaining_len))
}
}
impl<'a, T: 'a, const N: usize> DoubleEndedIterator for Drain<'a, T, N> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.remaining_len == 0 {
None
} else {
unsafe {
let e = self.vec.as_ref()
.as_ptr()
.add(self.remaining_start + self.remaining_len - 1)
.read();
self.remaining_len -= 1;
Some(e)
}
}
}
}
impl<'a, T: 'a, const N: usize> ExactSizeIterator for Drain<'a, T, N> { }
impl<'a, T: 'a, const N: usize> FusedIterator for Drain<'a, T, N> { }
impl<'a, T: 'a, const N: usize> Drop for Drain<'a, T, N> {
fn drop(&mut self) {
for e in &mut *self { drop(e) }
unsafe {
let vec = self.vec.as_mut();
let len = vec.len();
let ptr = vec.as_mut_ptr();
let src = ptr.add(self.tail_start);
let dst = ptr.add(len);
ptr::copy(src, dst, self.tail_len);
vec.set_len(len + self.tail_len);
}
}
}