1use core::{
2 iter::FusedIterator,
3 mem::transmute,
4 ptr::{metadata, DynMetadata, Pointee},
5};
6
7use crate::DynSlice;
8
9pub struct Iter<'a, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>>> {
11 pub(crate) slice: DynSlice<'a, Dyn>,
12}
13
14impl<'a, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>> + 'a> Clone for Iter<'a, Dyn> {
15 fn clone(&self) -> Self {
16 Self { slice: self.slice }
17 }
18}
19
20impl<'a, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>> + 'a> Iterator for Iter<'a, Dyn> {
21 type Item = &'a Dyn;
22
23 fn next(&mut self) -> Option<Self::Item> {
24 if self.slice.is_empty() {
25 None
26 } else {
27 let element: &'a Dyn = unsafe { transmute(self.slice.first_unchecked()) };
33
34 self.slice.data = unsafe { self.slice.data.byte_add(metadata(element).size_of()) };
39 self.slice.len -= 1;
40
41 Some(element)
42 }
43 }
44
45 #[inline]
46 fn size_hint(&self) -> (usize, Option<usize>) {
47 let remaining = self.slice.len();
48 (remaining, Some(remaining))
49 }
50
51 #[inline]
52 fn count(self) -> usize {
53 self.slice.len()
54 }
55
56 fn nth(&mut self, n: usize) -> Option<Self::Item> {
57 if n >= self.slice.len() {
58 self.slice.len = 0;
59 return None;
60 }
61
62 let metadata: DynMetadata<Dyn> = unsafe { transmute(self.slice.vtable_ptr) };
66
67 self.slice.data = unsafe { self.slice.data.byte_add(metadata.size_of() * n) };
71 self.slice.len -= n;
72
73 self.next()
74 }
75
76 fn last(self) -> Option<Self::Item> {
77 unsafe { transmute(self.slice.last()) }
81 }
82}
83
84impl<'a, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>> + 'a> DoubleEndedIterator
85 for Iter<'a, Dyn>
86{
87 fn next_back(&mut self) -> Option<Self::Item> {
88 if self.slice.is_empty() {
89 None
90 } else {
91 let element: &'a Dyn =
92 unsafe { transmute(self.slice.get_unchecked(self.slice.len - 1)) };
98
99 self.slice.len -= 1;
100
101 Some(element)
102 }
103 }
104
105 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
106 if n >= self.slice.len() {
107 self.slice.len = 0;
108 return None;
109 }
110
111 self.slice.len -= n;
112
113 self.next_back()
114 }
115}
116
117impl<'a, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>> + 'a> ExactSizeIterator
118 for Iter<'a, Dyn>
119{
120 #[inline]
121 fn len(&self) -> usize {
122 self.slice.len()
123 }
124}
125
126impl<'a, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>> + 'a> FusedIterator for Iter<'a, Dyn> {}
127
128#[cfg(test)]
129mod test {
130 use crate::standard::partial_eq;
131
132 #[test]
133 fn test_next() {
134 let array = [2, 3, 5, 7, 11];
135 let slice = partial_eq::new::<u8, _>(&array);
136
137 let mut iter = slice.iter();
138 for &expected in &array {
139 let actual = iter.next().expect("expected an element");
140 assert!(actual == &expected, "expected {expected}");
141 }
142 }
143
144 #[test]
145 fn test_size_hint() {
146 let array = [2, 3, 5, 7, 11];
147 let slice = partial_eq::new::<u8, _>(&array);
148
149 let mut iter = slice.iter();
150 for expected in (1..=array.len()).rev() {
151 let (lower, Some(upper)) = iter.size_hint() else {
152 panic!("expected an upper bound");
153 };
154
155 assert_eq!(lower, upper, "expected lower and upper bounds to be equal");
156 assert_eq!(
157 lower, expected,
158 "expected size hint to be {expected}, got {lower}"
159 );
160
161 let _ = iter.next().expect("expected an element");
162 }
163
164 let (lower, Some(upper)) = iter.size_hint() else {
165 panic!("expected an upper bound");
166 };
167
168 assert_eq!(lower, upper, "expected lower and upper bounds to be equal");
169 assert_eq!(lower, 0, "expected size hint to be 0, got {lower}");
170 }
171
172 #[test]
173 fn test_count() {
174 let array = [2, 3, 5, 7, 11];
175 let slice = partial_eq::new::<u8, _>(&array);
176
177 let mut iter = slice.iter();
178 for expected in (1..=array.len()).rev() {
179 let actual = iter.clone().count();
180 assert_eq!(
181 actual, expected,
182 "expected count to be {expected}, got {actual}"
183 );
184
185 let _ = iter.next().expect("expected an element");
186 }
187
188 let actual = iter.count();
189 assert_eq!(actual, 0, "expected count to be 0, got {actual}");
190 }
191
192 #[test]
193 fn test_nth() {
194 let array = [2, 3, 5, 7, 11];
195 let slice = partial_eq::new::<u8, _>(&array);
196
197 let mut iter = slice.iter();
198
199 #[allow(clippy::iter_nth_zero)]
200 let actual = iter.nth(0).expect("expected an element");
201 assert!(actual == &2, "expected 2");
202
203 assert!(
204 iter.nth(1).expect("expected an element") == &5,
205 "expected 5"
206 );
207 assert_eq!(iter.size_hint().0, 2, "expected 2 elements left");
208
209 assert!(iter.nth(2).is_none(), "expected none");
210 assert_eq!(iter.size_hint().0, 0, "expected 0 elements left");
211 }
212
213 #[test]
214 fn test_last() {
215 let array = [2, 3, 5, 7, 11];
216 let slice = partial_eq::new::<u8, _>(&array);
217
218 assert!(
219 slice.iter().last().expect("expected an element") == &11,
220 "expected 11"
221 );
222 }
223
224 #[test]
225 fn test_next_back() {
226 let array = [2, 3, 5, 7, 11];
227 let slice = partial_eq::new::<u8, _>(&array);
228
229 let mut iter = slice.iter();
230 for &expected in array.iter().rev() {
231 let actual = iter.next_back().expect("expected an element");
232 assert!(actual == &expected, "expected {expected}");
233 }
234 }
235
236 #[test]
237 fn test_nth_back() {
238 let array = [2, 3, 5, 7, 11];
239 let slice = partial_eq::new::<u8, _>(&array);
240
241 let mut iter = slice.iter();
242
243 #[allow(clippy::iter_nth_zero)]
244 let actual = iter.nth_back(0).expect("expected an element");
245 assert!(actual == &11, "expected 11");
246
247 assert!(
248 iter.nth_back(1).expect("expected an element") == &5,
249 "expected 5"
250 );
251 assert_eq!(iter.size_hint().0, 2, "expected 2 elements left");
252
253 assert!(iter.nth_back(2).is_none(), "expected none");
254 assert_eq!(iter.size_hint().0, 0, "expected 0 elements left");
255 }
256
257 #[test]
258 fn test_bidirectional() {
259 let array = [2, 3, 5, 7, 11];
260 let slice = partial_eq::new::<u8, _>(&array);
261
262 let mut iter = slice.iter();
263
264 assert!(
265 iter.next().expect("expected an element") == &2,
266 "expected 2"
267 );
268 assert_eq!(iter.size_hint().0, 4, "expected 4 elements left");
269
270 assert!(
271 iter.next_back().expect("expected an element") == &11,
272 "expected 11"
273 );
274 assert_eq!(iter.size_hint().0, 3, "expected 3 elements left");
275
276 assert!(
277 iter.nth(1).expect("expected an element") == &5,
278 "expected 5"
279 );
280 assert_eq!(iter.size_hint().0, 1, "expected 1 element left");
281
282 assert!(
283 iter.nth_back(0).expect("expected an element") == &7,
284 "expected 7"
285 );
286 assert_eq!(iter.size_hint().0, 0, "expected 0 elements left");
287 }
288}