]> git.lizzy.rs Git - rust.git/blob - library/alloc/src/vec/splice.rs
Auto merge of #104990 - matthiaskrgr:rollup-oskk8v3, r=matthiaskrgr
[rust.git] / library / alloc / src / vec / splice.rs
1 use crate::alloc::{Allocator, Global};
2 use core::ptr::{self};
3 use core::slice::{self};
4
5 use super::{Drain, Vec};
6
7 /// A splicing iterator for `Vec`.
8 ///
9 /// This struct is created by [`Vec::splice()`].
10 /// See its documentation for more.
11 ///
12 /// # Example
13 ///
14 /// ```
15 /// let mut v = vec![0, 1, 2];
16 /// let new = [7, 8];
17 /// let iter: std::vec::Splice<_> = v.splice(1.., new);
18 /// ```
19 #[derive(Debug)]
20 #[stable(feature = "vec_splice", since = "1.21.0")]
21 pub struct Splice<
22     'a,
23     I: Iterator + 'a,
24     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global,
25 > {
26     pub(super) drain: Drain<'a, I::Item, A>,
27     pub(super) replace_with: I,
28 }
29
30 #[stable(feature = "vec_splice", since = "1.21.0")]
31 impl<I: Iterator, A: Allocator> Iterator for Splice<'_, I, A> {
32     type Item = I::Item;
33
34     fn next(&mut self) -> Option<Self::Item> {
35         self.drain.next()
36     }
37
38     fn size_hint(&self) -> (usize, Option<usize>) {
39         self.drain.size_hint()
40     }
41 }
42
43 #[stable(feature = "vec_splice", since = "1.21.0")]
44 impl<I: Iterator, A: Allocator> DoubleEndedIterator for Splice<'_, I, A> {
45     fn next_back(&mut self) -> Option<Self::Item> {
46         self.drain.next_back()
47     }
48 }
49
50 #[stable(feature = "vec_splice", since = "1.21.0")]
51 impl<I: Iterator, A: Allocator> ExactSizeIterator for Splice<'_, I, A> {}
52
53 #[stable(feature = "vec_splice", since = "1.21.0")]
54 impl<I: Iterator, A: Allocator> Drop for Splice<'_, I, A> {
55     fn drop(&mut self) {
56         self.drain.by_ref().for_each(drop);
57
58         unsafe {
59             if self.drain.tail_len == 0 {
60                 self.drain.vec.as_mut().extend(self.replace_with.by_ref());
61                 return;
62             }
63
64             // First fill the range left by drain().
65             if !self.drain.fill(&mut self.replace_with) {
66                 return;
67             }
68
69             // There may be more elements. Use the lower bound as an estimate.
70             // FIXME: Is the upper bound a better guess? Or something else?
71             let (lower_bound, _upper_bound) = self.replace_with.size_hint();
72             if lower_bound > 0 {
73                 self.drain.move_tail(lower_bound);
74                 if !self.drain.fill(&mut self.replace_with) {
75                     return;
76                 }
77             }
78
79             // Collect any remaining elements.
80             // This is a zero-length vector which does not allocate if `lower_bound` was exact.
81             let mut collected = self.replace_with.by_ref().collect::<Vec<I::Item>>().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     unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool {
101         let vec = unsafe { self.vec.as_mut() };
102         let range_start = vec.len;
103         let range_end = self.tail_start;
104         let range_slice = unsafe {
105             slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start)
106         };
107
108         for place in range_slice {
109             if let Some(new_item) = replace_with.next() {
110                 unsafe { ptr::write(place, new_item) };
111                 vec.len += 1;
112             } else {
113                 return false;
114             }
115         }
116         true
117     }
118
119     /// Makes room for inserting more elements before the tail.
120     unsafe fn move_tail(&mut self, additional: usize) {
121         let vec = unsafe { self.vec.as_mut() };
122         let len = self.tail_start + self.tail_len;
123         vec.buf.reserve(len, additional);
124
125         let new_tail_start = self.tail_start + additional;
126         unsafe {
127             let src = vec.as_ptr().add(self.tail_start);
128             let dst = vec.as_mut_ptr().add(new_tail_start);
129             ptr::copy(src, dst, self.tail_len);
130         }
131         self.tail_start = new_tail_start;
132     }
133 }