1use core::{fmt, iter, mem, ptr};
4
5pub struct StackIntoIter<T, const N: usize> {
30 items: [mem::MaybeUninit<T>; N],
31 top_len: usize,
32 bottom_len: usize,
33}
34
35impl<T, const N: usize> StackIntoIter<T, N> {
36 #[inline]
38 pub(super) const unsafe fn new(items: [mem::MaybeUninit<T>; N], top_len: usize) -> Self {
39 Self {
41 items,
42 top_len,
43 bottom_len: 0,
44 }
45 }
46
47 #[inline]
50 fn pop_top(&mut self) -> Option<T> {
51 debug_assert!(self.bottom_len <= self.top_len);
52 if self.top_len == self.bottom_len {
53 None
54 } else {
55 self.top_len -= 1;
56 Some(unsafe { ptr::read(self.items.as_ptr().add(self.top_len)).assume_init() })
57 }
58 }
59
60 #[inline]
62 fn pop_bottom(&mut self) -> Option<T> {
63 debug_assert!(self.bottom_len <= self.top_len);
64
65 if self.bottom_len == self.top_len {
66 None
67 } else {
68 let result =
71 Some(unsafe { ptr::read(self.items.as_ptr().add(self.bottom_len)).assume_init() });
72 self.bottom_len += 1;
73 result
74 }
75 }
76}
77
78impl<T, const N: usize> Iterator for StackIntoIter<T, N> {
79 type Item = T;
80
81 #[inline]
82 fn next(&mut self) -> Option<Self::Item> {
83 self.pop_top()
84 }
85
86 #[inline]
87 fn size_hint(&self) -> (usize, Option<usize>) {
88 (self.bottom_len, Some(self.top_len))
89 }
90}
91
92impl<T, const N: usize> iter::DoubleEndedIterator for StackIntoIter<T, N> {
93 #[inline]
94 fn next_back(&mut self) -> Option<Self::Item> {
95 self.pop_bottom()
96 }
97}
98
99impl<T, const N: usize> Default for StackIntoIter<T, N> {
100 #[inline]
101 fn default() -> Self {
102 Self {
103 top_len: 0,
104 bottom_len: 0,
105
106 items: unsafe { mem::MaybeUninit::uninit().assume_init() },
108 }
109 }
110}
111
112impl<T, const N: usize> Clone for StackIntoIter<T, N>
113where
114 T: Clone,
115{
116 #[inline]
117 fn clone(&self) -> Self {
118 unsafe {
123 let mut items = mem::MaybeUninit::<[mem::MaybeUninit<T>; N]>::uninit().assume_init();
124 self.items
125 .get_unchecked(self.bottom_len..self.top_len)
126 .iter()
127 .zip(items.get_unchecked_mut(self.bottom_len..self.top_len))
128 .for_each(|(src, dst)| {
129 dst.write(src.assume_init_ref().clone());
130 });
131 Self {
132 items,
133 top_len: self.top_len,
134 bottom_len: self.bottom_len,
135 }
136 }
137 }
138}
139
140impl<T, const N: usize> Drop for StackIntoIter<T, N> {
141 #[inline]
142 fn drop(&mut self) {
143 debug_assert!(self.bottom_len <= self.top_len);
144
145 unsafe {
147 let items = self.items.get_unchecked_mut(self.bottom_len..self.top_len)
148 as *mut [mem::MaybeUninit<T>] as *mut [T];
149 ptr::drop_in_place(items);
150 }
151 }
152}
153
154impl<T, const N: usize> fmt::Debug for StackIntoIter<T, N>
155where
156 T: fmt::Debug,
157{
158 #[inline]
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160 let mut list = f.debug_list();
161
162 unsafe {
163 list.entries(
164 self.items
165 .get_unchecked(self.bottom_len..self.top_len)
166 .iter()
167 .map(|item| item.assume_init_ref()),
168 );
169 }
170
171 list.finish()
172 }
173}
174
175impl<T, const N: usize> iter::FusedIterator for StackIntoIter<T, N> {}
176
177impl<T, const N: usize, const M: usize> PartialEq<StackIntoIter<T, M>> for StackIntoIter<T, N>
178where
179 T: PartialEq,
180{
181 #[inline]
182 fn eq(&self, other: &StackIntoIter<T, M>) -> bool {
183 unsafe {
184 let items1 = self.items.get_unchecked(self.bottom_len..self.top_len)
185 as *const [mem::MaybeUninit<T>] as *const [T];
186 let items2 = other.items.get_unchecked(other.bottom_len..other.top_len)
187 as *const [mem::MaybeUninit<T>] as *const [T];
188 *items1 == *items2
189 }
190 }
191}
192
193