|
12 | 12 |
|
13 | 13 | use std::marker::Unsize;
|
14 | 14 | use std::iter::Extend;
|
15 |
| -use std::ptr::{self, drop_in_place}; |
| 15 | +use std::ptr::{self, drop_in_place, Shared}; |
16 | 16 | use std::ops::{Deref, DerefMut, Range};
|
17 | 17 | use std::hash::{Hash, Hasher};
|
18 | 18 | use std::slice;
|
19 | 19 | use std::fmt;
|
20 | 20 | use std::mem;
|
| 21 | +use std::collections::range::RangeArgument; |
21 | 22 |
|
22 | 23 | pub unsafe trait Array {
|
23 | 24 | type Element;
|
@@ -103,6 +104,44 @@ impl<A: Array> ArrayVec<A> {
|
103 | 104 | None
|
104 | 105 | }
|
105 | 106 | }
|
| 107 | + |
| 108 | + pub fn drain<R>(&mut self, range: R) -> Drain<A> |
| 109 | + where R: RangeArgument<usize> |
| 110 | + { |
| 111 | + // Memory safety |
| 112 | + // |
| 113 | + // When the Drain is first created, it shortens the length of |
| 114 | + // the source vector to make sure no uninitalized or moved-from elements |
| 115 | + // are accessible at all if the Drain's destructor never gets to run. |
| 116 | + // |
| 117 | + // Drain will ptr::read out the values to remove. |
| 118 | + // When finished, remaining tail of the vec is copied back to cover |
| 119 | + // the hole, and the vector length is restored to the new length. |
| 120 | + // |
| 121 | + let len = self.len(); |
| 122 | + let start = *range.start().unwrap_or(&0); |
| 123 | + let end = *range.end().unwrap_or(&len); |
| 124 | + assert!(start <= end); |
| 125 | + assert!(end <= len); |
| 126 | + |
| 127 | + unsafe { |
| 128 | + // set self.vec length's to start, to be safe in case Drain is leaked |
| 129 | + self.set_len(start); |
| 130 | + // Use the borrow in the IterMut to indicate borrowing behavior of the |
| 131 | + // whole Drain iterator (like &mut T). |
| 132 | + let range_slice = { |
| 133 | + let arr = &mut self.values as &mut [ManuallyDrop<_>]; |
| 134 | + slice::from_raw_parts_mut(arr.as_mut_ptr().offset(start as isize), |
| 135 | + end - start) |
| 136 | + }; |
| 137 | + Drain { |
| 138 | + tail_start: end, |
| 139 | + tail_len: len - end, |
| 140 | + iter: range_slice.iter(), |
| 141 | + array_vec: Shared::new(self as *mut _), |
| 142 | + } |
| 143 | + } |
| 144 | + } |
106 | 145 | }
|
107 | 146 |
|
108 | 147 | impl<A> Default for ArrayVec<A>
|
@@ -179,6 +218,51 @@ impl<A: Array> Iterator for Iter<A> {
|
179 | 218 | }
|
180 | 219 | }
|
181 | 220 |
|
| 221 | +pub struct Drain<'a, A: Array> |
| 222 | + where A::Element: 'a |
| 223 | +{ |
| 224 | + tail_start: usize, |
| 225 | + tail_len: usize, |
| 226 | + iter: slice::Iter<'a, ManuallyDrop<A::Element>>, |
| 227 | + array_vec: Shared<ArrayVec<A>>, |
| 228 | +} |
| 229 | + |
| 230 | +impl<'a, A: Array> Iterator for Drain<'a, A> { |
| 231 | + type Item = A::Element; |
| 232 | + |
| 233 | + #[inline] |
| 234 | + fn next(&mut self) -> Option<A::Element> { |
| 235 | + self.iter.next().map(|elt| unsafe { ptr::read(elt as *const ManuallyDrop<_>).value }) |
| 236 | + } |
| 237 | + |
| 238 | + fn size_hint(&self) -> (usize, Option<usize>) { |
| 239 | + self.iter.size_hint() |
| 240 | + } |
| 241 | +} |
| 242 | + |
| 243 | +impl<'a, A: Array> Drop for Drain<'a, A> { |
| 244 | + fn drop(&mut self) { |
| 245 | + // exhaust self first |
| 246 | + while let Some(_) = self.next() {} |
| 247 | + |
| 248 | + if self.tail_len > 0 { |
| 249 | + unsafe { |
| 250 | + let source_array_vec = &mut **self.array_vec; |
| 251 | + // memmove back untouched tail, update to new length |
| 252 | + let start = source_array_vec.len(); |
| 253 | + let tail = self.tail_start; |
| 254 | + { |
| 255 | + let mut arr = &mut source_array_vec.values as &mut [ManuallyDrop<_>]; |
| 256 | + let src = arr.as_ptr().offset(tail as isize); |
| 257 | + let dst = arr.as_mut_ptr().offset(start as isize); |
| 258 | + ptr::copy(src, dst, self.tail_len); |
| 259 | + }; |
| 260 | + source_array_vec.set_len(start + self.tail_len); |
| 261 | + } |
| 262 | + } |
| 263 | + } |
| 264 | +} |
| 265 | + |
182 | 266 | impl<A: Array> IntoIterator for ArrayVec<A> {
|
183 | 267 | type Item = A::Element;
|
184 | 268 | type IntoIter = Iter<A>;
|
|
0 commit comments