| 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 | |