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}