standard_lib/collections/contiguous/array/iter.rs
1use std::alloc;
2use std::iter::{FusedIterator, TrustedLen};
3use std::marker::PhantomData;
4use std::mem;
5use std::ptr::{self, NonNull};
6
7use super::Array;
8#[allow(unused)]
9use crate::collections::contiguous::Vector;
10
11impl<T> IntoIterator for Array<T> {
12 type Item = T;
13
14 type IntoIter = IntoIter<T>;
15
16 fn into_iter(self) -> Self::IntoIter {
17 let head = self.ptr.as_ptr().cast_const();
18 let result = IntoIter {
19 ptr: self.ptr,
20 size: self.size,
21 head,
22 // Don't subtract 1 for the tail.
23 // SAFETY: Offset of one won't overflow isize::MAX. The memory range between head and
24 // tail will be the same as that of the Array, where the initial value of tail is never
25 // read.
26 tail: unsafe { head.add(self.size) },
27 _phantom: PhantomData,
28 };
29 mem::forget(self);
30 result
31 }
32}
33
34/// A type for owned iteration over an [`Array`] or [`Vector`]. Produces values of type `T`.
35///
36/// See [`Array::into_iter`] and [`Vector::into_iter`].
37pub struct IntoIter<T> {
38 pub(crate) ptr: NonNull<T>,
39 pub(crate) size: usize,
40 pub(crate) head: *const T, // Head points to the first element.
41 pub(crate) tail: *const T, // Tail points one after the last element.
42 pub(crate) _phantom: PhantomData<T>,
43}
44
45impl<T> Drop for IntoIter<T> {
46 fn drop(&mut self) {
47 while self.head < self.tail {
48 // SAFETY: The pointer is nonnull, properly aligned and valid for both reads and writes.
49 // This method takes a mutable reference to self, so the underlying data can't be
50 // mutated while it executes.
51 unsafe { ptr::drop_in_place(self.head.cast_mut()) }
52 // SAFETY: Offset of one won't overflow isize::MAX. If the resulting pointer meets
53 // tail it won't ever be read, preventing reads out of bounds of the original Array.
54 self.head = unsafe { self.head.add(1) };
55 }
56
57 let layout = Array::<T>::make_layout(self.size);
58
59 if layout.size() != 0 {
60 // SAFETY: ptr is ensured to be valid by the Array used to create this Iterator.
61 // Zero-sized layouts aren't allocated and are guarded against deallocation.
62 unsafe {
63 alloc::dealloc(self.ptr.as_ptr().cast(), layout)
64 }
65 }
66 }
67}
68
69impl<T> Iterator for IntoIter<T> {
70 type Item = T;
71
72 fn next(&mut self) -> Option<Self::Item> {
73 if self.head < self.tail {
74 // SAFETY: The pointer is always valid for reads. We will increment the pointer next so
75 // that the value is effectively moved off of the heap.
76 let value = unsafe { self.head.read() };
77 // SAFETY: Offset of one won't overflow isize::MAX. If the resulting pointer meets
78 // tail it won't ever be read, preventing reads out of bounds of the original Array.
79 self.head = unsafe { self.head.add(1) };
80 Some(value)
81 } else {
82 None
83 }
84 }
85
86 fn size_hint(&self) -> (usize, Option<usize>) {
87 let len = self.len();
88 (len, Some(len))
89 }
90}
91
92impl<T> DoubleEndedIterator for IntoIter<T> {
93 fn next_back(&mut self) -> Option<Self::Item> {
94 if self.head < self.tail {
95 // Tail sits one after the end, so we subtract first then read. Results in the same
96 // number of operations and an accurate length calculation with subtraction.
97 // SAFETY: Offset of one won't overflow isize::MAX. If the resulting pointer meets
98 // head it won't ever be read, preventing reads out of bounds of the original Array.
99 self.tail = unsafe { self.tail.sub(1) };
100 // SAFETY: The pointer is always valid for reads and we've just decremented it so that
101 // the previous value is never read and effectively moved off of the heap.
102 Some(unsafe { self.tail.read() })
103 } else {
104 None
105 }
106 }
107}
108
109impl<T> FusedIterator for IntoIter<T> {}
110
111impl<T> ExactSizeIterator for IntoIter<T> {
112 fn len(&self) -> usize {
113 // SAFETY: Both pointers are derived from the original allocation and aligned to multiple of
114 // size_of::<T>(). The memory range between them is contained within the initial allocation.
115 // tail is at worst equal to head, it can't be less than.
116 unsafe { self.tail.offset_from_unsigned(self.head) }
117 }
118}
119
120// SAFETY: IntoIter::size_hint returns the exact length of the iterator.
121unsafe impl<T> TrustedLen for IntoIter<T> {}
122
123// Just use the iter and iter_mut definitions provided by Deref<Target=[T]>.