smallvec 2.0.0-beta.4

'Small vector' optimization: store up to a small number of items on the stack
Documentation
use {
    super::{
        super::{
            SmallVec,
            allocator::{
                Allocator,
                global::Global,
                proxy::Proxy
            }
        },
        drain::Drain
    },
    core::fmt::{
        Debug,
        Formatter,
        Result as Format
    }
};

pub struct Splice<'valid, I: Iterator + 'valid, const INLINE: usize, Heap: Allocator = Global> {
    drain: Drain<'valid, I::Item, INLINE, Heap>,
    replace_with: I
}

impl<'valid, I: Iterator + 'valid, const INLINE: usize, Heap: Allocator>
    Splice<'valid, I, INLINE, Heap>
{
    pub(crate) fn new(drain: Drain<'valid, I::Item, INLINE, Heap>, replace_with: I) -> Self {
        Self {
            drain,
            replace_with
        }
    }
}

impl<'valid, I, const INLINE: usize, Heap: Allocator> Debug for Splice<'valid, I, INLINE, Heap>
where
    I: Debug + Iterator + 'valid,
    <I as Iterator>::Item: Debug
{
    fn fmt(&self, f: &mut Formatter<'_>) -> Format {
        f.debug_tuple("Splice").field(&self.drain).finish()
    }
}

impl<I: Iterator, const INLINE: usize, Heap: Allocator> Iterator for Splice<'_, I, INLINE, Heap> {
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        self.drain.next()
    }

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

impl<I: Iterator, const INLINE: usize, Heap: Allocator> DoubleEndedIterator
    for Splice<'_, I, INLINE, Heap>
{
    fn next_back(&mut self) -> Option<Self::Item> {
        self.drain.next_back()
    }
}

impl<I: Iterator, const INLINE: usize, Heap: Allocator> ExactSizeIterator
    for Splice<'_, I, INLINE, Heap>
{
}

impl<I: Iterator, const INLINE: usize, Heap: Allocator> Drop for Splice<'_, I, INLINE, Heap> {
    fn drop(&mut self) {
        self.drain.by_ref().for_each(drop);
        // At this point draining is done and the only remaining tasks are
        // splicing and moving things into the final place.
        // Which means we can replace the slice::Iter with pointers that won't
        // point to deallocated memory, so that Drain::drop is still
        // allowed to call iter.len(), otherwise it would break the
        // ptr.sub_ptr contract.
        self.drain.iter = [].iter();

        unsafe {
            if self.drain.tail_len == 0 {
                self.drain.vec.as_mut().extend(self.replace_with.by_ref());
                return;
            }

            // First fill the range left by drain().
            if !self.drain.fill(&mut self.replace_with) {
                return;
            }

            // There may be more elements. Use the lower bound as an estimate.
            // FIXME: Is the upper bound a better guess? Or something else?
            let (lower_bound, _upper_bound) = self.replace_with.size_hint();
            if lower_bound > 0 {
                self.drain.move_tail(lower_bound);
                if !self.drain.fill(&mut self.replace_with) {
                    return;
                }
            }

            let mut smallvec =
                SmallVec::<_, INLINE, _>::new_in(Proxy(&self.drain.vec.as_ref().allocator));
            smallvec.extend(self.replace_with.by_ref());
            let mut collected = smallvec.into_iter();

            // Now we have an exact count.
            if collected.len() > 0 {
                self.drain.move_tail(collected.len());
                let filled = self.drain.fill(&mut collected);
                debug_assert!(filled);
                debug_assert_eq!(collected.len(), 0);
            }
        }
        // Let `Drain::drop` move the tail back if necessary and restore
        // `vec.length`.
    }
}