rc-vec 0.1.14

RcVec based on Rc and can be converted from Rc without allocation
Documentation
use core::{
    fmt::Debug,
    iter::FusedIterator,
    mem::take,
    ptr::{self, NonNull},
    slice,
};
use crate::is_zst::IsZst;
use rc_vec_proc_macro::rc_impl_gen_arc_impl;

use super::{ArcVec, RcVec};

#[rc_impl_gen_arc_impl]
pub struct RcVecDrain<'a, T: 'a> {
    pub(super) tail_start: usize,
    pub(super) tail_len: usize,
    pub(super) iter: slice::Iter<'a, T>,
    pub(super) vec: NonNull<RcVec<T>>,
}

impl<'a, T: Debug + 'a> Debug for RcVecDrain<'a, T> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_tuple("RcVecDrain")
            .field(&self.iter.as_slice())
            .finish()
    }
}

impl<'a, T: Debug + 'a> Debug for ArcVecDrain<'a, T> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_tuple("ArcVecDrain")
            .field(&self.iter.as_slice())
            .finish()
    }
}

#[rc_impl_gen_arc_impl]
impl<'a, T: 'a> RcVecDrain<'a, T> {
    pub fn as_slice(&self) -> &[T] {
        self.iter.as_slice()
    }
}

#[rc_impl_gen_arc_impl]
impl<'a, T: 'a> Iterator for RcVecDrain<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|ele| unsafe { ptr::read(ele) })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

#[rc_impl_gen_arc_impl]
impl<'a, T: 'a> DoubleEndedIterator for RcVecDrain<'a, T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iter.next_back().map(|ele| unsafe { ptr::read(ele) })
    }
}

#[rc_impl_gen_arc_impl]
struct RcVecMoveGuard<'r, 'a, T>(&'r mut RcVecDrain<'a, T>);

#[rc_impl_gen_arc_impl]
impl<'r, 'a, T> Drop for RcVecMoveGuard<'r, 'a, T> {
    fn drop(&mut self) {
        unsafe {
            let src_vec = self.0.vec.as_mut();
            let start = src_vec.len();
            let tail = self.0.tail_start;

            if tail != start {
                let dest = src_vec.as_mut_ptr().add(start);
                src_vec.as_ptr().add(tail)
                    .copy_to(dest, self.0.tail_len);
            }

            src_vec.set_len(start+self.0.tail_len);
        }
    }
}

#[rc_impl_gen_arc_impl]
impl<'a, T: 'a> Drop for RcVecDrain<'a, T> {
    fn drop(&mut self) {
        let iter = take(&mut self.iter);
        let drop_len = iter.len();

        let mut vec = self.vec;

        if T::ZST {
            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 = RcVecMoveGuard(self);

        if drop_len == 0 {
            return;
        }

        let drop_ptr = iter.as_slice().as_ptr();

        unsafe {
            let vec_ptr = vec.as_mut().as_ptr();
            let drop_offset = drop_ptr.offset_from(vec_ptr).try_into().unwrap();
            let range = drop_offset..drop_offset+drop_len;
            vec.as_mut().raw.drop_elems_from_range(range);
        }
    }
}

#[rc_impl_gen_arc_impl]
impl<T> ExactSizeIterator for RcVecDrain<'_, T> { }

#[rc_impl_gen_arc_impl]
impl<T> FusedIterator for RcVecDrain<'_, T> { }