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}