dyn_vec 0.1.0

A Vec<T: ?Sized>
Documentation
//! Iteration.

use std::{marker::PhantomData, mem::ManuallyDrop, ptr::NonNull};

use crate::{ptr_ext::PtrExt, DynVec};

struct BaseIter<T: ?Sized> {
    ptr: *const *mut T,
    ptr_back: *const *mut T,
}

unsafe impl<T: Send> Send for BaseIter<T> {}
unsafe impl<T: Sync> Sync for BaseIter<T> {}

impl<T: ?Sized> BaseIter<T> {
    pub(crate) fn new(vec: &DynVec<T>) -> Self {
        Self {
            ptr: vec.get_ptr_to_extra(vec.len).cast(),
            ptr_back: vec.get_ptr_to_extra(0).cast(),
        }
    }
}

impl<T: ?Sized> Iterator for BaseIter<T> {
    type Item = *mut T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.ptr == self.ptr_back {
            return None;
        }

        self.ptr_back = self.ptr_back.wrapping_sub(1);
        Some(unsafe { self.ptr_back.read() })
    }
}

impl<T: ?Sized> DoubleEndedIterator for BaseIter<T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.ptr == self.ptr_back {
            return None;
        }

        let el = unsafe { self.ptr.read() };
        self.ptr = self.ptr.wrapping_add(1);
        Some(el)
    }
}

// By-ref iteration
impl<T: ?Sized> DynVec<T> {
    /// Iterates over the vector by-ref.
    pub fn iter(&self) -> Iter<T> {
        Iter {
            base: BaseIter::new(self),
            _phantom: PhantomData,
        }
    }
}

impl<'a, T: ?Sized> IntoIterator for &'a DynVec<T> {
    type Item = &'a T;

    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

/// A by-ref iterator over the elements of a [`DynVec`].
pub struct Iter<'a, T: ?Sized> {
    base: BaseIter<T>,
    _phantom: PhantomData<&'a T>,
}

unsafe impl<'a, T: Send> Send for Iter<'a, T> {}
unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {}

impl<'a, T: ?Sized> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        self.base.next().map(|v| unsafe { &*v })
    }
}

impl<'a, T: ?Sized> DoubleEndedIterator for Iter<'a, T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.base.next_back().map(|v| unsafe { &*v })
    }
}

// By-mut iteration
impl<T: ?Sized> DynVec<T> {
    /// Iterates over the vector by-mut.
    pub fn iter_mut(&mut self) -> IterMut<T> {
        IterMut {
            base: BaseIter::new(self),
            _phantom: PhantomData,
        }
    }
}

impl<'a, T: ?Sized> IntoIterator for &'a mut DynVec<T> {
    type Item = &'a mut T;

    type IntoIter = IterMut<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

/// A by-mut iterator over the elements of a [`DynVec`].
#[allow(clippy::module_name_repetitions)]
pub struct IterMut<'a, T: ?Sized> {
    base: BaseIter<T>,
    _phantom: PhantomData<&'a mut T>,
}

unsafe impl<'a, T: Send> Send for IterMut<'a, T> {}
unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {}

impl<'a, T: ?Sized> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<Self::Item> {
        self.base.next().map(|v| unsafe { &mut *v })
    }
}

impl<'a, T: ?Sized> DoubleEndedIterator for IterMut<'a, T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.base.next_back().map(|v| unsafe { &mut *v })
    }
}

// By-value iteration
impl<T: ?Sized> IntoIterator for DynVec<T> {
    type Item = Box<T>;

    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        let this = ManuallyDrop::new(self);
        IntoIter {
            ptr: this.ptr,
            capacity: this.capacity,
            base: BaseIter::new(&this),
        }
    }
}

/// A by-value iterator over the elements of a [`DynVec`].
#[allow(clippy::module_name_repetitions)]
pub struct IntoIter<T: ?Sized> {
    ptr: NonNull<u8>,
    capacity: usize,
    base: BaseIter<T>,
}

unsafe impl<T: Send> Send for IntoIter<T> {}
unsafe impl<T: Sync> Sync for IntoIter<T> {}

impl<T: ?Sized> Iterator for IntoIter<T> {
    type Item = Box<T>;

    fn next(&mut self) -> Option<Self::Item> {
        Some(unsafe { self.base.next()?.read_to_box() })
    }
}

impl<T: ?Sized> DoubleEndedIterator for IntoIter<T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        Some(unsafe { self.base.next_back()?.read_to_box() })
    }
}

impl<T: ?Sized> Drop for IntoIter<T> {
    fn drop(&mut self) {
        drop(DynVec::<T> {
            ptr: self.ptr,
            len: 0,
            capacity: self.capacity,
            end_ptr: self.ptr,
            _phantom: PhantomData,
        });
    }
}

// // this implementation will collect *while unsizing*, and would conflict with the other
// impl<T: ?Sized, U> FromIterator<U> for DynVec<T> where for<'a> &'a U: CoerceUnsized<&'a T> {
//     fn from_iter<I: IntoIterator<Item = U>>(iter: I) -> Self {
//         let mut vec = DynVec::new();

//         for item in iter.into_iter() {
//             vec.push_unsize(item);
//         }

//         vec
//     }
// }

impl<T> FromIterator<T> for DynVec<T> {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        let mut vec = Self::new();

        for item in iter {
            vec.push(item);
        }

        vec
    }
}