1 | use core::ptr::{self};
|
2 | use core::slice::{self};
|
3 |
|
4 | use crate::stable::alloc::{Allocator, Global};
|
5 |
|
6 | use super::{Drain, Vec};
|
7 |
|
8 | /// A splicing iterator for `Vec`.
|
9 | ///
|
10 | /// This struct is created by [`Vec::splice()`].
|
11 | /// See its documentation for more.
|
12 | ///
|
13 | /// # Example
|
14 | ///
|
15 | /// ```
|
16 | /// let mut v = vec![0, 1, 2];
|
17 | /// let new = [7, 8];
|
18 | /// let iter: std::vec::Splice<_> = v.splice(1.., new);
|
19 | /// ```
|
20 | #[derive (Debug)]
|
21 | pub struct Splice<'a, I: Iterator + 'a, A: Allocator + 'a = Global> {
|
22 | pub(super) drain: Drain<'a, I::Item, A>,
|
23 | pub(super) replace_with: I,
|
24 | }
|
25 |
|
26 | impl<I: Iterator, A: Allocator> Iterator for Splice<'_, I, A> {
|
27 | type Item = I::Item;
|
28 |
|
29 | #[inline (always)]
|
30 | fn next(&mut self) -> Option<Self::Item> {
|
31 | self.drain.next()
|
32 | }
|
33 |
|
34 | #[inline (always)]
|
35 | fn size_hint(&self) -> (usize, Option<usize>) {
|
36 | self.drain.size_hint()
|
37 | }
|
38 | }
|
39 |
|
40 | impl<I: Iterator, A: Allocator> DoubleEndedIterator for Splice<'_, I, A> {
|
41 | #[inline (always)]
|
42 | fn next_back(&mut self) -> Option<Self::Item> {
|
43 | self.drain.next_back()
|
44 | }
|
45 | }
|
46 |
|
47 | impl<I: Iterator, A: Allocator> ExactSizeIterator for Splice<'_, I, A> {}
|
48 |
|
49 | impl<I: Iterator, A: Allocator> Drop for Splice<'_, I, A> {
|
50 | #[inline ]
|
51 | fn drop(&mut self) {
|
52 | self.drain.by_ref().for_each(drop);
|
53 |
|
54 | unsafe {
|
55 | if self.drain.tail_len == 0 {
|
56 | self.drain.vec.as_mut().extend(self.replace_with.by_ref());
|
57 | return;
|
58 | }
|
59 |
|
60 | // First fill the range left by drain().
|
61 | if !self.drain.fill(&mut self.replace_with) {
|
62 | return;
|
63 | }
|
64 |
|
65 | // There may be more elements. Use the lower bound as an estimate.
|
66 | // FIXME: Is the upper bound a better guess? Or something else?
|
67 | let (lower_bound, _upper_bound) = self.replace_with.size_hint();
|
68 | if lower_bound > 0 {
|
69 | self.drain.move_tail(lower_bound);
|
70 | if !self.drain.fill(&mut self.replace_with) {
|
71 | return;
|
72 | }
|
73 | }
|
74 |
|
75 | // Collect any remaining elements.
|
76 | // This is a zero-length vector which does not allocate if `lower_bound` was exact.
|
77 | let mut collected = self
|
78 | .replace_with
|
79 | .by_ref()
|
80 | .collect::<Vec<I::Item>>()
|
81 | .into_iter();
|
82 | // Now we have an exact count.
|
83 | if collected.len() > 0 {
|
84 | self.drain.move_tail(collected.len());
|
85 | let filled = self.drain.fill(&mut collected);
|
86 | debug_assert!(filled);
|
87 | debug_assert_eq!(collected.len(), 0);
|
88 | }
|
89 | }
|
90 | // Let `Drain::drop` move the tail back if necessary and restore `vec.len`.
|
91 | }
|
92 | }
|
93 |
|
94 | /// Private helper methods for `Splice::drop`
|
95 | impl<T, A: Allocator> Drain<'_, T, A> {
|
96 | /// The range from `self.vec.len` to `self.tail_start` contains elements
|
97 | /// that have been moved out.
|
98 | /// Fill that range as much as possible with new elements from the `replace_with` iterator.
|
99 | /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.)
|
100 | #[inline (always)]
|
101 | unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool {
|
102 | let vec = unsafe { self.vec.as_mut() };
|
103 | let range_start = vec.len;
|
104 | let range_end = self.tail_start;
|
105 | let range_slice = unsafe {
|
106 | slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start)
|
107 | };
|
108 |
|
109 | for place in range_slice {
|
110 | if let Some(new_item) = replace_with.next() {
|
111 | unsafe { ptr::write(place, new_item) };
|
112 | vec.len += 1;
|
113 | } else {
|
114 | return false;
|
115 | }
|
116 | }
|
117 | true
|
118 | }
|
119 |
|
120 | /// Makes room for inserting more elements before the tail.
|
121 | #[inline (always)]
|
122 | unsafe fn move_tail(&mut self, additional: usize) {
|
123 | let vec = unsafe { self.vec.as_mut() };
|
124 | let len = self.tail_start + self.tail_len;
|
125 | vec.buf.reserve(len, additional);
|
126 |
|
127 | let new_tail_start = self.tail_start + additional;
|
128 | unsafe {
|
129 | let src = vec.as_ptr().add(self.tail_start);
|
130 | let dst = vec.as_mut_ptr().add(new_tail_start);
|
131 | ptr::copy(src, dst, self.tail_len);
|
132 | }
|
133 | self.tail_start = new_tail_start;
|
134 | }
|
135 | }
|
136 | |