extern crate alloc;
use core::fmt;
use core::ptr;
use core::slice;
use crate::allocator::{AllocatorProvider, Global};
use crate::vec::drain::Drain;
use crate::vec::types::EcoVec;
pub struct Splice<'a, I: Iterator + 'a, A: AllocatorProvider + Clone = Global>
where
I::Item: Clone,
{
pub(crate) drain: Drain<'a, I::Item, A>,
pub(crate) replace_with: I,
}
impl<I, A> fmt::Debug for Splice<'_, I, A>
where
I: Iterator + fmt::Debug,
I::Item: Clone + fmt::Debug,
A: AllocatorProvider + Clone,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Splice")
.field("drain", &self.drain)
.field("replace_with", &self.replace_with)
.finish()
}
}
impl<I: Iterator, A: AllocatorProvider + Clone> Iterator for Splice<'_, I, A>
where
I::Item: Clone,
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.drain.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.drain.size_hint()
}
}
impl<I: Iterator, A: AllocatorProvider + Clone> DoubleEndedIterator for Splice<'_, I, A>
where
I::Item: Clone,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.drain.next_back()
}
}
impl<I: Iterator, A: AllocatorProvider + Clone> ExactSizeIterator for Splice<'_, I, A> where
I::Item: Clone
{
}
impl<I: Iterator, A> Drop for Splice<'_, I, A>
where
I::Item: Clone,
A: AllocatorProvider + Clone,
{
fn drop(&mut self) {
self.drain.by_ref().for_each(drop);
self.drain.iter = [].iter();
unsafe {
if self.drain.tail_len == 0 {
self.drain.vec.as_mut().extend(self.replace_with.by_ref());
return;
}
if !self.drain.fill(&mut self.replace_with) {
return;
}
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 collected = self
.replace_with
.by_ref()
.collect::<alloc::vec::Vec<I::Item>>()
.into_iter();
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);
}
}
}
}
impl<T: Clone, A: AllocatorProvider + Clone> Drain<'_, T, A> {
unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool {
let vec = unsafe { self.vec.as_mut() };
let range_start = vec.len();
let range_end = self.tail_start;
let range_slice = unsafe {
slice::from_raw_parts_mut(
vec.data_mut().add(range_start),
range_end - range_start,
)
};
for place in range_slice {
let Some(new_item) = replace_with.next() else {
return false;
};
unsafe { ptr::write(place, new_item) };
vec.len += 1;
}
true
}
unsafe fn move_tail(&mut self, additional: usize) {
let vec = unsafe { self.vec.as_mut() };
let len = self.tail_start + self.tail_len;
let capacity = vec.capacity();
if additional > capacity - len {
let saved_len = vec.len;
debug_assert_eq!(saved_len, self.tail_start);
vec.len = len;
vec.reserve(additional);
vec.len = saved_len;
}
let new_tail_start = self.tail_start + additional;
unsafe {
let src = vec.data().add(self.tail_start);
let dst = vec.data_mut().add(new_tail_start);
ptr::copy(src, dst, self.tail_len);
}
self.tail_start = new_tail_start;
}
}
impl<T, A> EcoVec<T, A>
where
T: Clone,
A: AllocatorProvider + Clone,
{
#[inline]
pub fn splice<R, I>(
&mut self,
range: R,
replace_with: I,
) -> Splice<'_, I::IntoIter, A>
where
R: core::ops::RangeBounds<usize>,
I: IntoIterator<Item = T>,
{
Splice {
drain: self.drain(range),
replace_with: replace_with.into_iter(),
}
}
}