bump_scope/owned_slice/
into_iter.rs1use core::{
2 fmt::Debug,
3 iter::FusedIterator,
4 marker::PhantomData,
5 mem::{self, ManuallyDrop},
6 ops::Range,
7 ptr::NonNull,
8 slice,
9};
10
11use crate::{BumpBox, SizedTypeProperties, polyfill::non_null};
12
13use super::TakeOwnedSlice;
14
15pub struct IntoIter<'a, T> {
24 ptr: NonNull<T>,
25 end: NonNull<T>, marker: PhantomData<(&'a (), T)>,
30}
31
32unsafe impl<T: Send> Send for IntoIter<'_, T> {}
33unsafe impl<T: Sync> Sync for IntoIter<'_, T> {}
34
35impl<T: Debug> Debug for IntoIter<'_, T> {
36 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
37 f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
38 }
39}
40
41impl<T> Default for IntoIter<'_, T> {
42 fn default() -> Self {
43 Self::EMPTY
44 }
45}
46
47impl<'a, T> IntoIter<'a, T> {
48 pub const EMPTY: Self = IntoIter {
50 ptr: NonNull::dangling(),
51 end: NonNull::dangling(),
52 marker: PhantomData,
53 };
54
55 #[inline(always)]
56 pub(crate) unsafe fn new(slice: NonNull<[T]>) -> Self {
57 unsafe {
58 if T::IS_ZST {
59 Self::new_zst(slice.len())
60 } else {
61 let start = slice.cast::<T>();
62 let end = start.add(slice.len());
63 Self::new_range(start..end)
64 }
65 }
66 }
67
68 #[inline(always)]
69 pub(crate) unsafe fn new_ranged(ptr: NonNull<[T]>, range: Range<usize>) -> Self {
70 unsafe {
71 if T::IS_ZST {
72 Self::new_zst(range.end - range.start)
73 } else {
74 let ptr = non_null::as_non_null_ptr(ptr);
75 let start = ptr.add(range.start);
76 let end = ptr.add(range.end);
77 Self::new_range(start..end)
78 }
79 }
80 }
81
82 #[inline(always)]
83 fn new_zst(len: usize) -> Self {
84 assert!(T::IS_ZST);
85
86 Self {
87 ptr: NonNull::dangling(),
88 end: unsafe { non_null::wrapping_byte_add(NonNull::dangling(), len) },
89 marker: PhantomData,
90 }
91 }
92
93 #[inline(always)]
94 unsafe fn new_range(range: Range<NonNull<T>>) -> Self {
95 assert!(!T::IS_ZST);
96
97 Self {
98 ptr: range.start,
99 end: range.end,
100 marker: PhantomData,
101 }
102 }
103
104 #[must_use]
106 #[inline(always)]
107 pub fn len(&self) -> usize {
108 if T::IS_ZST {
109 self.end.addr().get().wrapping_sub(self.ptr.addr().get())
110 } else {
111 unsafe { non_null::offset_from_unsigned(self.end, self.ptr) }
112 }
113 }
114
115 #[must_use]
117 #[inline(always)]
118 pub fn is_empty(&self) -> bool {
119 self.ptr == self.end
120 }
121
122 #[must_use]
124 #[inline(always)]
125 pub fn as_slice(&self) -> &[T] {
126 unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len()) }
127 }
128
129 #[must_use]
131 #[inline(always)]
132 pub fn as_mut_slice(&mut self) -> &mut [T] {
133 unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len()) }
134 }
135
136 #[must_use]
142 #[inline(always)]
143 pub fn into_boxed_slice(self) -> BumpBox<'a, [T]> {
144 let this = ManuallyDrop::new(self);
145
146 unsafe {
147 let slice = NonNull::slice_from_raw_parts(this.ptr, this.len());
148 BumpBox::from_raw(slice)
149 }
150 }
151}
152
153impl<T> Iterator for IntoIter<'_, T> {
154 type Item = T;
155
156 #[inline(always)]
157 fn next(&mut self) -> Option<Self::Item> {
158 if self.ptr == self.end {
159 None
160 } else if T::IS_ZST {
161 self.end = unsafe { non_null::wrapping_byte_sub(self.end, 1) };
165
166 Some(unsafe { mem::zeroed() })
168 } else {
169 unsafe {
170 let old = self.ptr;
171 self.ptr = self.ptr.add(1);
172 Some(old.as_ptr().read())
173 }
174 }
175 }
176
177 #[inline(always)]
178 fn size_hint(&self) -> (usize, Option<usize>) {
179 let exact = self.len();
180 (exact, Some(exact))
181 }
182
183 #[inline(always)]
184 fn count(self) -> usize {
185 self.len()
186 }
187}
188
189impl<T> DoubleEndedIterator for IntoIter<'_, T> {
190 #[inline(always)]
191 fn next_back(&mut self) -> Option<Self::Item> {
192 if self.end == self.ptr {
193 None
194 } else if T::IS_ZST {
195 self.end = unsafe { non_null::wrapping_byte_sub(self.end, 1) };
199
200 Some(unsafe { mem::zeroed() })
202 } else {
203 unsafe {
204 self.end = self.end.sub(1);
205 Some(self.end.as_ptr().read())
206 }
207 }
208 }
209}
210
211impl<T> ExactSizeIterator for IntoIter<'_, T> {
212 #[inline(always)]
213 fn len(&self) -> usize {
214 IntoIter::len(self)
215 }
216}
217
218impl<T> FusedIterator for IntoIter<'_, T> {}
219
220impl<T> Drop for IntoIter<'_, T> {
221 #[inline]
222 fn drop(&mut self) {
223 unsafe {
224 NonNull::slice_from_raw_parts(self.ptr, self.len()).as_ptr().drop_in_place();
225 }
226 }
227}
228
229unsafe impl<T> TakeOwnedSlice for IntoIter<'_, T> {
231 type Item = T;
232
233 #[inline]
234 fn owned_slice_ref(&self) -> &[Self::Item] {
235 self.as_slice()
236 }
237
238 #[inline]
239 fn take_owned_slice(&mut self) {
240 self.ptr = self.end;
242 }
243}