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