use core::fmt;
use core::iter::FusedIterator;
use core::ops::RangeBounds;
use allocator_api2::alloc::Allocator;
use super::Vec;
impl<'a, T, A: Allocator + Clone> Vec<'a, T, A> {
pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, 'a, I::IntoIter, A>
where
R: RangeBounds<usize>,
I: IntoIterator<Item = T>,
{
Splice {
drain: self.drain(range),
replace_with: replace_with.into_iter(),
}
}
}
pub struct Splice<'d, 'a, I: Iterator, A: Allocator + Clone> {
drain: super::Drain<'d, 'a, I::Item, A>,
replace_with: I,
}
impl<I: Iterator, A: Allocator + Clone> fmt::Debug for Splice<'_, '_, I, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Splice").field("remaining", &self.drain.len()).finish()
}
}
impl<I: Iterator, A: Allocator + Clone> Iterator for Splice<'_, '_, I, A> {
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
self.drain.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.drain.size_hint()
}
}
impl<I: Iterator, A: Allocator + Clone> DoubleEndedIterator for Splice<'_, '_, I, A> {
#[inline]
fn next_back(&mut self) -> Option<I::Item> {
self.drain.next_back()
}
}
impl<I: Iterator, A: Allocator + Clone> ExactSizeIterator for Splice<'_, '_, I, A> {}
impl<I: Iterator, A: Allocator + Clone> FusedIterator for Splice<'_, '_, I, A> {}
impl<I: Iterator, A: Allocator + Clone> Drop for Splice<'_, '_, I, A> {
fn drop(&mut self) {
self.drain.by_ref().for_each(drop);
let (mut vec_ptr, insert_at) = unsafe { self.drain.close_tail() };
let vec = unsafe { vec_ptr.as_mut() };
let before = vec.len();
for item in self.replace_with.by_ref() {
vec.push(item);
}
let added = vec.len() - before;
vec.as_mut_slice()[insert_at..].rotate_right(added);
}
}