tiny_vec/
drain.rs

1//! [drain](TinyVec::drain) implementation
2//!
3use crate::TinyVec;
4use core::iter::FusedIterator;
5use core::marker::PhantomData;
6use core::mem::{self, ManuallyDrop};
7use core::ops::{Bound, RangeBounds};
8use core::ptr::{self, NonNull};
9use core::slice;
10
11/// A draining iterator for [TinyVec]
12///
13/// This struct is created by the [TinyVec::drain] method
14pub struct Drain<'a, T: 'a, const N: usize> {
15    remaining_start: usize,
16    remaining_len: usize,
17    tail_start: usize,
18    tail_len: usize,
19    vec: NonNull<TinyVec<T, N>>,
20    _marker: PhantomData<&'a mut TinyVec<T, N>>,
21}
22
23impl<'a, T: 'a, const N: usize> Drain<'a, T, N> {
24
25    /// Returns the remaining elements as a slice
26    #[inline]
27    pub fn as_slice(&self) -> &[T] {
28        unsafe {
29            let ptr = self.vec.as_ref().as_ptr().add(self.remaining_start);
30            slice::from_raw_parts(ptr, self.remaining_len)
31        }
32    }
33
34    /// Consumes this [Drain], preserving any un-yielded elements
35    ///
36    /// # Example
37    /// ```
38    /// use tiny_vec::TinyVec;
39    ///
40    /// let mut tv = TinyVec::from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
41    ///
42    /// let mut drain = tv.drain(3..7);
43    ///
44    /// assert_eq!(drain.next(), Some(3));
45    /// assert_eq!(drain.next(), Some(4));
46    ///
47    /// drain.keep_rest();
48    ///
49    /// assert_eq!(tv.as_slice(), &[0, 1, 2, 5, 6, 7, 8, 9]);
50    /// ```
51    pub fn keep_rest(self) {
52        let mut slf = ManuallyDrop::new(self);
53
54        /* [ HEAD ] [ yieled  | remaining | yielded_back ] [ TAIL ]
55         *         ^          ^           ^                ^
56         *         |          |           |                |
57         *      vec.len   iter.ptr  (iter.ptr + iter.len)  tail_start
58         * */
59        unsafe {
60            let vec = slf.vec.as_mut();
61            let start = vec.len();
62
63            if mem::size_of::<T>() != 0 {
64                let buf = vec.as_mut_ptr();
65
66                let start_ptr = buf.add(start);
67                let remaining_ptr = buf.add(slf.remaining_start);
68
69                if remaining_ptr != start_ptr {
70                    /* First: We move the remaining chunk to the start */
71                    ptr::copy(remaining_ptr, start_ptr, slf.remaining_len);
72                }
73
74                if slf.tail_start != (start + slf.remaining_len) {
75                    let src = buf.add(slf.tail_start);
76                    let dst = start_ptr.add(slf.remaining_len);
77                    /* Now we move the tail */
78                    ptr::copy(src, dst, slf.tail_len);
79                }
80            }
81            vec.set_len(start + slf.remaining_len + slf.tail_len);
82        }
83    }
84}
85
86impl<'a, T: 'a, const N: usize> Iterator for Drain<'a, T, N> {
87    type Item = T;
88
89    fn next(&mut self) -> Option<Self::Item> {
90        if self.remaining_len == 0 {
91            None
92        } else {
93            unsafe {
94                let e = self.vec.as_ref().as_ptr().add(self.remaining_start).read();
95                self.remaining_start += 1;
96                self.remaining_len -= 1;
97                Some(e)
98            }
99        }
100    }
101
102    fn size_hint(&self) -> (usize, Option<usize>) {
103        (self.remaining_len, Some(self.remaining_len))
104    }
105}
106
107impl<'a, T: 'a, const N: usize> DoubleEndedIterator for Drain<'a, T, N> {
108    fn next_back(&mut self) -> Option<Self::Item> {
109        if self.remaining_len == 0 {
110            None
111        } else {
112            unsafe {
113                let e = self.vec.as_ref()
114                                .as_ptr()
115                                .add(self.remaining_start + self.remaining_len - 1)
116                                .read();
117                self.remaining_len -= 1;
118                Some(e)
119            }
120        }
121    }
122}
123
124impl<'a, T: 'a, const N: usize> ExactSizeIterator for Drain<'a, T, N> { }
125
126impl<'a, T: 'a, const N: usize> FusedIterator for Drain<'a, T, N> { }
127
128impl<'a, T: 'a, const N: usize> Drop for Drain<'a, T, N> {
129    fn drop(&mut self) {
130        /* FIXME: The std implementation does some complex
131         * thing with a DropGuard struct. */
132        for e in &mut *self { drop(e) }
133        unsafe {
134            let vec = self.vec.as_mut();
135
136            let len = vec.len();
137            let ptr = vec.as_mut_ptr();
138
139            let src = ptr.add(self.tail_start);
140            let dst = ptr.add(len);
141
142            ptr::copy(src, dst, self.tail_len);
143
144            vec.set_len(len + self.tail_len);
145        }
146    }
147}
148
149impl<T, const N: usize> TinyVec<T, N> {
150
151    /// Removes the subslice indicated by the given range from the vector,
152    /// returning a double-ended iterator over the removed subslice.
153    ///
154    /// If the iterator is dropped before being fully consumed,
155    /// it drops the remaining removed elements.
156    ///
157    /// # Panics
158    ///
159    /// Panics if the starting point is greater than the end point or if
160    /// the end point is greater than the length of the vector.
161    ///
162    /// # Leaking
163    ///
164    /// If the returned iterator goes out of scope without being dropped (due to
165    /// [`mem::forget`], for example), the vector may have lost and leaked
166    /// elements arbitrarily, including elements outside the range.
167    ///
168    /// # Examples
169    ///
170    /// ```
171    /// use tiny_vec::{tinyvec, TinyVec};
172    /// let mut v: TinyVec<_, 10> = tinyvec![0, 1, 2, 3, 4, 5, 6];
173    /// let mut drain = v.drain(2..=4);
174    /// assert_eq!(drain.next(), Some(2));
175    /// assert_eq!(drain.next(), Some(3));
176    /// assert_eq!(drain.next(), Some(4));
177    /// assert_eq!(drain.next(), None);
178    /// drop(drain);
179    ///
180    /// assert_eq!(v, &[0, 1, 5, 6]);
181    ///
182    /// // A full range clears the vector, like `clear()` does
183    /// v.drain(..);
184    /// assert_eq!(v, &[]);
185    /// ```
186    pub fn drain<R>(&mut self, range: R) -> Drain<T, N>
187    where
188        R: RangeBounds<usize>
189    {
190
191        let len = self.len();
192
193        let start = match range.start_bound() {
194            Bound::Included(n) => *n,
195            Bound::Excluded(n) => *n + 1,
196            Bound::Unbounded => 0,
197        };
198
199        let end = match range.end_bound() {
200            Bound::Included(n) => *n + 1,
201            Bound::Excluded(n) => *n,
202            Bound::Unbounded => len,
203        };
204
205        assert!(start <= end);
206        assert!(end <= len);
207
208        unsafe {
209            self.set_len(start);
210
211            Drain {
212                vec: NonNull::new_unchecked(self as *mut _),
213                remaining_start: start,
214                remaining_len: end - start,
215                tail_start: end,
216                tail_len: len - end,
217                _marker: PhantomData,
218            }
219        }
220    }
221}