1use core::ptr::{self};
2use core::slice::{self};
3
4use crate::alloc::Allocator;
5use crate::error::Error;
6
7use super::{Drain, Vec};
8
9pub(crate) fn splice<'a, I, A>(
13 drain: &mut Drain<'a, I::Item, A>,
14 replace_with: &mut I,
15) -> Result<(), Error>
16where
17 I: Iterator + 'a,
18 A: Allocator + 'a,
19{
20 for element in drain.by_ref() {
21 drop(element);
22 }
23
24 drain.iter = [].iter();
30
31 unsafe {
32 if drain.tail_len == 0 {
33 let out = drain.vec.as_mut();
34
35 for element in replace_with.by_ref() {
36 out.try_push(element)?;
37 }
38
39 return Ok(());
40 }
41
42 if !drain.fill(replace_with) {
44 return Ok(());
45 }
46
47 let (lower_bound, _upper_bound) = replace_with.size_hint();
50
51 if lower_bound > 0 {
52 drain.move_tail(lower_bound)?;
53
54 if !drain.fill(replace_with) {
55 return Ok(());
56 }
57 }
58
59 let mut collected = Vec::new_in(drain.vec.as_ref().allocator());
62
63 for element in replace_with.by_ref() {
64 collected.try_push(element)?;
65 }
66
67 let mut collected = collected.into_iter();
68
69 if collected.len() > 0 {
71 drain.move_tail(collected.len())?;
72 let filled = drain.fill(&mut collected);
73 debug_assert!(filled);
74 debug_assert_eq!(collected.len(), 0);
75 }
76
77 Ok(())
78 }
79 }
81
82impl<T, A> Drain<'_, T, A>
84where
85 A: Allocator,
86{
87 unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool {
92 let vec = unsafe { self.vec.as_mut() };
93 let range_start = vec.len;
94 let range_end = self.tail_start;
95 let range_slice = unsafe {
96 slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start)
97 };
98
99 for place in range_slice {
100 if let Some(new_item) = replace_with.next() {
101 unsafe { ptr::write(place, new_item) };
102 vec.len += 1;
103 } else {
104 return false;
105 }
106 }
107 true
108 }
109
110 unsafe fn move_tail(&mut self, additional: usize) -> Result<(), Error> {
112 let vec = unsafe { self.vec.as_mut() };
113 let len = self.tail_start + self.tail_len;
114 vec.buf.try_reserve(len, additional)?;
115
116 let new_tail_start = self.tail_start + additional;
117 unsafe {
118 let src = vec.as_ptr().add(self.tail_start);
119 let dst = vec.as_mut_ptr().add(new_tail_start);
120 ptr::copy(src, dst, self.tail_len);
121 }
122 self.tail_start = new_tail_start;
123 Ok(())
124 }
125}