use core::mem::MaybeUninit;
use super::Vec;
use crate::{Align, Alloc, Allocator};
pub struct IntoIter<'alloc, T> {
buf: Alloc<'alloc, T>,
len: usize,
i: usize,
}
impl<'alloc, T> IntoIter<'alloc, T> {
pub fn new<S: crate::Strategy>(mut vec: Vec<'alloc, T, S>) -> Self {
let len = vec.len;
let allocator = vec.state.allocator();
let buf = vec
.state
.take()
.map(|(buf, _)| buf)
.unwrap_or_else(|| allocator.dangling(Align::of::<T>()).cast());
vec.len = 0;
Self { buf, len, i: 0 }
}
pub fn allocator(&self) -> &'alloc dyn Allocator {
self.buf.allocator()
}
fn buf_mut(&mut self, from: usize) -> &mut [MaybeUninit<T>] {
let start = self.len.min(from);
let ptr = unsafe { self.buf.as_ptr().add(start).cast() };
let slice = core::ptr::slice_from_raw_parts_mut(ptr, self.len - start);
unsafe { &mut *slice }
}
}
impl<T> Iterator for IntoIter<'_, T> {
type Item = T;
fn next(&mut self) -> Option<T> {
if self.i >= self.len {
return None;
}
self.i += 1;
let i = self.i - 1;
let buf = self.buf_mut(i);
Some(unsafe { buf[0].assume_init_read() })
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len - self.i;
(len, Some(len))
}
}
impl<T> ExactSizeIterator for IntoIter<'_, T> {}
impl<T> Drop for IntoIter<'_, T> {
fn drop(&mut self) {
for element in self.buf_mut(self.i) {
unsafe { element.assume_init_drop() };
}
let dangling = self.buf.allocator().dangling(Align::of::<T>()).cast();
self.len = 0;
self.i = 0;
core::mem::replace(&mut self.buf, dangling).dealloc();
}
}