1use core::iter::FusedIterator;
4use core::marker::PhantomData;
5use core::mem::{self, ManuallyDrop, MaybeUninit};
6use core::num::NonZero;
7use core::ptr;
8
9use alloc::slice;
10
11use crate::raw::RawVec;
12use crate::TinyVec;
13
14enum Kind<T, const N: usize> {
15 Stack([MaybeUninit<T>; N]),
16 Heap(RawVec<T>),
17}
18
19impl<T, const N: usize> Kind<T, N> {
20 const fn ptr(&self) -> *const T {
21 match self {
22 Kind::Stack(s) => s.as_ptr().cast(),
23 Kind::Heap(rv) => rv.ptr.as_ptr()
24 }
25 }
26
27 const fn ptr_mut(&mut self) -> *mut T {
28 match self {
29 Kind::Stack(s) => s.as_mut_ptr().cast(),
30 Kind::Heap(rv) => rv.ptr.as_ptr()
31 }
32 }
33}
34
35pub struct TinyVecIter<T, const N: usize> {
39 start: usize,
40 len: usize,
41 buf: Kind<T, N>,
42 _marker: PhantomData<TinyVec<T, N>>,
43}
44
45impl<T, const N: usize> TinyVecIter<T, N> {
46 pub const fn as_slice(&self) -> &[T] {
48 unsafe {
49 let ptr = self.buf.ptr().add(self.start);
50 slice::from_raw_parts(ptr, self.len)
51 }
52 }
53
54 pub const fn as_mut_slice(&mut self) -> &mut [T] {
56 unsafe {
57 let ptr = self.buf.ptr_mut().add(self.start);
58 slice::from_raw_parts_mut(ptr, self.len)
59 }
60 }
61}
62
63impl<T, const N: usize> Drop for TinyVecIter<T, N> {
64 fn drop(&mut self) {
65 let raw = match self.buf {
66 Kind::Stack(_) => None,
67 Kind::Heap(raw) => Some(raw),
68 };
69
70 if mem::needs_drop::<T>() {
71 for e in self {
72 mem::drop(e);
73 }
74 }
75
76 if let Some(mut raw) = raw {
77 unsafe { raw.destroy(); }
78 }
79 }
80}
81
82impl<T, const N: usize> TinyVecIter<T, N> {
83
84 #[inline(always)]
85 fn _advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
86 if n > self.len {
87 return Err(unsafe { NonZero::new_unchecked(n - self.len) })
90 }
91 self.len -= n;
92 self.start += n;
93 Ok(())
94 }
95
96 #[inline(always)]
97 fn _advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
98 if n > self.len {
99 return Err(unsafe { NonZero::new_unchecked(n - self.len) })
102 }
103 self.len -= n;
104 Ok(())
105 }
106
107 #[cfg(not(feature = "use-nightly-features"))]
108 #[inline(always)]
109 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
110 self._advance_back_by(n)
111 }
112
113 #[cfg(not(feature = "use-nightly-features"))]
114 #[inline(always)]
115 fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
116 self._advance_by(n)
117 }
118}
119
120impl<T, const N: usize> Iterator for TinyVecIter<T, N> {
121 type Item = T;
122
123 fn next(&mut self) -> Option<Self::Item> {
124 if self.len == 0 {
125 None
126 } else {
127 let e = unsafe {
128 self.buf
129 .ptr_mut()
130 .add(self.start)
131 .read()
132 };
133 self.start += 1;
134 self.len -= 1;
135 Some(e)
136 }
137 }
138
139 fn size_hint(&self) -> (usize, Option<usize>) {
140 (self.len, Some(self.len))
141 }
142
143 fn nth(&mut self, n: usize) -> Option<Self::Item> {
144 self.advance_by(n).ok()?;
145 self.next()
146 }
147
148 #[cfg(feature = "use-nightly-features")]
149 fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
150 self._advance_by(n)
151 }
152}
153
154impl<T, const N: usize> DoubleEndedIterator for TinyVecIter<T, N> {
155 fn next_back(&mut self) -> Option<Self::Item> {
156 if self.len == 0 {
157 None
158 } else {
159 self.len -= 1;
160 let e = unsafe {
161 self.buf
162 .ptr_mut()
163 .add(self.start + self.len)
164 .read()
165 };
166 Some(e)
167 }
168 }
169
170 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
171 self.advance_back_by(n).ok()?;
172 self.next_back()
173 }
174
175 #[cfg(feature = "use-nightly-features")]
176 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
177 self._advance_back_by(n)
178 }
179}
180
181impl<T, const N: usize> ExactSizeIterator for TinyVecIter<T, N> { }
182
183impl<T, const N: usize> FusedIterator for TinyVecIter<T, N> { }
184
185impl<T, const N: usize> IntoIterator for TinyVec<T, N> {
186 type Item = T;
187
188 type IntoIter = TinyVecIter<T, N>;
189
190 fn into_iter(self) -> Self::IntoIter {
191 let vec = ManuallyDrop::new(self);
192
193 let is_stack = vec.lives_on_stack();
194 let len = vec.len();
195
196 let buf = unsafe {
197 let inner = ptr::read( &vec.inner );
198 if is_stack {
199 Kind::Stack(ManuallyDrop::into_inner( inner.stack ))
200 } else {
201 Kind::Heap(inner.raw)
202 }
203 };
204
205 TinyVecIter { start: 0, len, buf, _marker: PhantomData }
206 }
207}
208
209#[cfg(test)]
210#[allow(clippy::iter_nth_zero)]
211mod test {
212 use crate::TinyVec;
213
214 #[test]
215 fn nth() {
216 let mut it = TinyVec::from([1, 2, 3, 4, 5, 6, 7]).into_iter();
217
218 assert_eq!(Some(3), it.nth(2));
219 assert_eq!(Some(4), it.nth(0));
220
221 assert_eq!(Some(6), it.nth_back(1));
222 assert_eq!(Some(5), it.nth_back(0));
223
224 assert_eq!(it.len(), 0);
225 }
226}