1use core::iter::{FusedIterator, Peekable};
2use core::marker::PhantomData;
3use core::ops::Range;
4use core::ptr;
5
6use super::buffer::VecBuffer;
7use super::drain::Drain;
8use super::index_panic;
9use crate::capacity::{Grow, Index};
10
11pub struct Splice<'s, I, B, G>
13where
14 I: Iterator,
15 B: VecBuffer<Item = I::Item>,
16 G: Grow,
17{
18 drain: Drain<'s, B>,
19 extend: Peekable<I>,
20 _pd: PhantomData<G>,
21}
22
23impl<'s, I, B, G> Splice<'s, I, B, G>
24where
25 I: Iterator,
26 B: VecBuffer<Item = I::Item>,
27 G: Grow,
28{
29 pub(super) fn new(vec: &'s mut B, extend: I, range: Range<usize>) -> Self {
30 let drain = Drain::new(vec, range);
31 Self {
32 drain,
33 extend: extend.peekable(),
34 _pd: PhantomData,
35 }
36 }
37
38 pub const fn is_empty(&self) -> bool {
40 self.drain.is_empty()
41 }
42
43 pub const fn len(&self) -> usize {
45 self.drain.len()
46 }
47}
48
49impl<'s, I, B, G> Iterator for Splice<'s, I, B, G>
50where
51 I: Iterator,
52 B: VecBuffer<Item = I::Item>,
53 G: Grow,
54{
55 type Item = I::Item;
56
57 fn next(&mut self) -> Option<Self::Item> {
58 self.drain.next()
59 }
60
61 #[inline]
62 fn count(self) -> usize
63 where
64 Self: Sized,
65 {
66 self.len()
67 }
68
69 #[inline]
70 fn size_hint(&self) -> (usize, Option<usize>) {
71 self.drain.size_hint()
72 }
73}
74
75impl<'s, I, B, G> DoubleEndedIterator for Splice<'s, I, B, G>
76where
77 I: Iterator,
78 B: VecBuffer<Item = I::Item>,
79 G: Grow,
80{
81 fn next_back(&mut self) -> Option<Self::Item> {
82 self.drain.next_back()
83 }
84}
85
86impl<'s, I, B, G> ExactSizeIterator for Splice<'s, I, B, G>
87where
88 I: Iterator,
89 B: VecBuffer<Item = I::Item>,
90 G: Grow,
91{
92}
93
94impl<'s, I, B, G> FusedIterator for Splice<'s, I, B, G>
95where
96 I: Iterator,
97 B: VecBuffer<Item = I::Item>,
98 G: Grow,
99{
100}
101
102impl<'s, I, B, G> Drop for Splice<'s, I, B, G>
103where
104 I: Iterator,
105 B: VecBuffer<Item = I::Item>,
106 G: Grow,
107{
108 fn drop(&mut self) {
109 self.drain.clear_remain();
110
111 while self.extend.peek().is_some() {
112 for index in self.drain.range.clone() {
113 if let Some(item) = self.extend.next() {
114 unsafe { self.drain.buf.uninit_index(index) }.write(item);
115 self.drain.range.start = index + 1;
116 } else {
117 return;
119 }
120 }
121
122 let mut buf_cap = self.drain.buf.capacity();
123 let (min_remain, max_remain) = self.extend.size_hint();
124 let cap_remain = buf_cap.to_usize() - self.drain.range.end - self.drain.tail_length;
125 if min_remain > cap_remain {
126 let new_cap =
127 B::Index::try_from_usize(buf_cap.to_usize() + min_remain - cap_remain)
128 .expect("exceeded range of capacity");
129 let new_cap = G::next_capacity::<B::Item, _>(buf_cap, new_cap);
130 match self.drain.buf.grow_buffer(new_cap, false) {
131 Ok(_) => (),
132 Err(err) => err.panic(),
133 }
134 buf_cap = new_cap;
135 }
136
137 if self.drain.tail_length > 0 {
140 let new_tail = self
141 .drain
142 .range
143 .end
144 .saturating_add(max_remain.unwrap_or_default().max(min_remain))
145 .min(buf_cap.to_usize());
146 let ins_count = new_tail - self.drain.range.end;
147 if ins_count < min_remain {
148 index_panic();
149 }
150 unsafe {
151 let head = self.drain.buf.data_ptr_mut().add(self.drain.range.end);
152 ptr::copy(head, head.add(ins_count), self.drain.tail_length);
153 }
154 self.drain.range.end += ins_count;
155 }
156 }
157 }
158}