bump_scope/bump_vec/
splice.rs1#![cfg(feature = "panic-on-alloc")]
2
3use core::{ptr, slice};
4
5use crate::{BumpAllocatorExt, BumpVec, destructure::destructure};
6
7use super::Drain;
8
9#[derive(Debug)]
28pub struct Splice<'a, I: Iterator + 'a, A: BumpAllocatorExt> {
29 pub(super) drain: Drain<'a, I::Item, A>,
30 pub(super) replace_with: I,
31}
32
33impl<I: Iterator, A: BumpAllocatorExt> Iterator for Splice<'_, I, A> {
34 type Item = I::Item;
35
36 #[inline]
37 fn next(&mut self) -> Option<Self::Item> {
38 self.drain.next()
39 }
40
41 #[inline]
42 fn size_hint(&self) -> (usize, Option<usize>) {
43 self.drain.size_hint()
44 }
45}
46
47impl<I: Iterator, A: BumpAllocatorExt> DoubleEndedIterator for Splice<'_, I, A> {
48 #[inline]
49 fn next_back(&mut self) -> Option<Self::Item> {
50 self.drain.next_back()
51 }
52}
53
54impl<I: Iterator, A: BumpAllocatorExt> ExactSizeIterator for Splice<'_, I, A> {}
55
56impl<I: Iterator, A: BumpAllocatorExt> Drop for Splice<'_, I, A> {
57 fn drop(&mut self) {
58 self.drain.by_ref().for_each(drop);
59 self.drain.iter = <[I::Item]>::iter(&[]);
65
66 unsafe {
67 if self.drain.tail_len == 0 {
68 self.drain.vec.as_mut().extend(self.replace_with.by_ref());
69 return;
70 }
71
72 if !self.drain.fill(&mut self.replace_with) {
74 return;
75 }
76
77 let (lower_bound, _upper_bound) = self.replace_with.size_hint();
80 if lower_bound > 0 {
81 self.drain.move_tail(lower_bound);
82 if !self.drain.fill(&mut self.replace_with) {
83 return;
84 }
85 }
86
87 let collected = BumpVec::from_iter_in(&mut self.replace_with, self.drain.vec.as_ref().allocator());
90
91 destructure!(let BumpVec::<I::Item, &A> { fixed: collected } = collected);
94 let mut collected = collected.cook().into_iter();
95
96 #[expect(clippy::len_zero)]
98 if collected.len() > 0 {
99 self.drain.move_tail(collected.len());
100 let filled = self.drain.fill(&mut collected);
101 debug_assert!(filled);
102 debug_assert_eq!(collected.len(), 0);
103 }
104 }
105 }
107}
108
109impl<T, A: BumpAllocatorExt> Drain<'_, T, A> {
111 unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool {
116 unsafe {
117 let vec = self.vec.as_mut();
118 let range_start = vec.len();
119 let range_end = self.tail_start;
120 let range_slice = slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start);
121
122 for place in range_slice {
123 match replace_with.next() {
124 Some(new_item) => {
125 ptr::write(place, new_item);
126 vec.inc_len(1);
127 }
128 _ => {
129 return false;
130 }
131 }
132 }
133 true
134 }
135 }
136
137 unsafe fn move_tail(&mut self, additional: usize) {
139 unsafe {
140 let vec = self.vec.as_mut();
141 let len = self.tail_start + self.tail_len;
142 vec.buf_reserve(len, additional);
143
144 let new_tail_start = self.tail_start + additional;
145
146 let src = vec.as_ptr().add(self.tail_start);
147 let dst = vec.as_mut_ptr().add(new_tail_start);
148 ptr::copy(src, dst, self.tail_len);
149
150 self.tail_start = new_tail_start;
151 }
152 }
153}