1use crate::*;
2
3pub(crate) fn slice_range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
4where
5 R: ops::RangeBounds<usize>,
6{
7 let len = bounds.end;
8
9 let start: ops::Bound<&usize> = range.start_bound();
10 let start = match start {
11 ops::Bound::Included(&start) => start,
12 ops::Bound::Excluded(start) => start
13 .checked_add(1)
14 .unwrap_or_else(|| panic!("attempted to index slice from after maximum usize")),
15 ops::Bound::Unbounded => 0,
16 };
17
18 let end: ops::Bound<&usize> = range.end_bound();
19 let end = match end {
20 ops::Bound::Included(end) => end
21 .checked_add(1)
22 .unwrap_or_else(|| panic!("attempted to index slice up to maximum usize")),
23 ops::Bound::Excluded(&end) => end,
24 ops::Bound::Unbounded => len,
25 };
26
27 if start > end {
28 panic!("slice index starts at {start} but ends at {end}");
29 }
30 if end > len {
31 panic!("range end index {end} out of range for slice of length {len}",);
32 }
33 ops::Range { start, end }
34}
35
36pub struct Drain<'a, T: 'a, A: Array<T>> {
37 pub(super) tail_start: usize,
39 pub(super) tail_len: usize,
41 pub(super) iter: slice::Iter<'a, T>,
43 pub(super) vec: NonNull<A>,
44}
45
46impl<T: fmt::Debug, A: Array<T>> fmt::Debug for Drain<'_, T, A> {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
49 }
50}
51
52impl<'a, T, A: Array<T>> Drain<'a, T, A> {
53 #[must_use]
65 pub fn as_slice(&self) -> &[T] {
66 self.iter.as_slice()
67 }
68}
69
70impl<'a, T, A: Array<T>> AsRef<[T]> for Drain<'a, T, A> {
71 fn as_ref(&self) -> &[T] {
72 self.as_slice()
73 }
74}
75
76unsafe impl<T: Sync, A: Sync + Array<T>> Sync for Drain<'_, T, A> {}
77unsafe impl<T: Send, A: Send + Array<T>> Send for Drain<'_, T, A> {}
78
79impl<T, A: Array<T>> Iterator for Drain<'_, T, A> {
80 type Item = T;
81
82 #[inline]
83 fn next(&mut self) -> Option<T> {
84 self.iter
85 .next()
86 .map(|elt| unsafe { ptr::read(elt as *const _) })
87 }
88
89 fn size_hint(&self) -> (usize, Option<usize>) {
90 self.iter.size_hint()
91 }
92}
93
94impl<T, A: Array<T>> DoubleEndedIterator for Drain<'_, T, A> {
95 #[inline]
96 fn next_back(&mut self) -> Option<T> {
97 self.iter
98 .next_back()
99 .map(|elt| unsafe { ptr::read(elt as *const _) })
100 }
101}
102
103impl<T, A: Array<T>> Drop for Drain<'_, T, A> {
104 fn drop(&mut self) {
105 struct DropGuard<'r, 'a, T, A: Array<T>>(&'r mut Drain<'a, T, A>);
107
108 impl<'r, 'a, T, A: Array<T>> Drop for DropGuard<'r, 'a, T, A> {
109 fn drop(&mut self) {
110 if self.0.tail_len > 0 {
111 unsafe {
112 let source_vec = self.0.vec.as_mut();
113 let start = source_vec.len();
115 let tail = self.0.tail_start;
116 if tail != start {
117 let src = source_vec.as_ptr().add(tail);
118 let dst = source_vec.as_mut_ptr().add(start);
119 ptr::copy(src, dst, self.0.tail_len);
120 }
121 source_vec.set_len(start + self.0.tail_len);
122 }
123 }
124 }
125 }
126
127 let iter = mem::replace(&mut self.iter, (& []).iter());
128 let drop_len = iter.len();
129
130 let mut vec = self.vec;
131
132 if mem::size_of::<T>() == 0 {
133 unsafe {
136 let vec = vec.as_mut();
137 let old_len = vec.len();
138 vec.set_len(old_len + drop_len + self.tail_len);
139 vec.truncate(old_len + self.tail_len);
140 }
141
142 return;
143 }
144
145 let _guard = DropGuard(self);
147
148 if drop_len == 0 {
149 return;
150 }
151
152 let drop_ptr = iter.as_slice().as_ptr();
157
158 unsafe {
159 let vec_ptr = vec.as_mut().as_mut_ptr();
164 let drop_offset = drop_ptr.offset_from(vec_ptr) as usize;
165 let to_drop = ptr::slice_from_raw_parts_mut(vec_ptr.add(drop_offset), drop_len);
166 ptr::drop_in_place(to_drop);
167 }
168 }
169}
170
171impl<T, A: Array<T>> core::iter::FusedIterator for Drain<'_, T, A> {}