realloc 0.1.0

A re-implementation of various ::alloc features
Documentation
// TODO: implement DoubleEndedIterator

use core::mem::MaybeUninit;

use super::Vec;
use crate::{Align, Alloc, Allocator};

/// An iterator that moves out of a vector.
/// 
/// This type is created by the `into_iter` method on [`Vec`] (provided by the
/// [`IntoIterator`](core::iter::IntoIterator) trait).
pub struct IntoIter<'alloc, T> {
    buf: Alloc<'alloc, T>,
    len: usize,
    i: usize,
}

impl<'alloc, T> IntoIter<'alloc, T> {
    /// Creates a new iterator from a vector.
    ///
    /// The `into_iter` method on [`Vec`] (provided by the
    /// [`IntoIterator`](core::iter::IntoIterator) trait) should be preferred.
    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 }
    }

    /// Returns a reference to the allocator underlying the original vector.
    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);
        // SAFETY: this will stay inside the bounds of the allocated object
        let ptr = unsafe { self.buf.as_ptr().add(start).cast() };
        let slice = core::ptr::slice_from_raw_parts_mut(ptr, self.len - start);
        // SAFETY: `MaybeUninit<T>` is always valid, the pointer is pointing at (worst-case) the
        // end of the buffer, and pointing to only valid elements
        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;
        }

        // Increment early to avoid problems with panics
        self.i += 1;
        let i = self.i - 1;
        let buf = self.buf_mut(i);
        // SAFETY: the item is initialized, and will never be seen again
        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) {
            // SAFETY: each of these elements is initialized, and will never be seen again
            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();
    }
}