1#[macro_export]
43macro_rules! forward_into_iterator {
44 (<$($generic:ident),+> in $($rest:tt)+) => {
45 $crate::forward_into_iterator!(@impl [$($generic),+] $($rest)+);
46 };
47
48 (<const $($rest:tt)+) => {
49 $crate::__impl_more_parse_generics!(@parse forward_into_iterator [] [] const $($rest)+);
50 };
51
52 (<$generic:ident, $($rest:tt)+) => {
53 $crate::__impl_more_parse_generics!(@parse forward_into_iterator [] [] $generic, $($rest)+);
54 };
55
56 (@impl [$($generic:tt)+] $this:ty => $field:tt : $inner:ty; $($mode:ident),+ $(,)?) => {
57 $crate::forward_into_iterator!(@modes [$($generic)+] $this => $field: $inner; $($mode),+);
58 };
59
60 (@impl [$($generic:tt)+] $this:ty => $inner:ty; $($mode:ident),+ $(,)?) => {
61 $crate::forward_into_iterator!(@modes [$($generic)+] $this => 0: $inner; $($mode),+);
62 };
63
64 ($this:ty => $field:tt : $inner:ty; $($mode:ident),+ $(,)?) => {
65 $crate::forward_into_iterator!(@modes [] $this => $field: $inner; $($mode),+);
66 };
67
68 ($this:ty => $inner:ty; $($mode:ident),+ $(,)?) => {
69 $crate::forward_into_iterator!(@modes [] $this => 0: $inner; $($mode),+);
70 };
71
72 (@modes $generics:tt $this:ty => $field:tt : $inner:ty; $($mode:ident),+) => {
73 $( $crate::forward_into_iterator!(@mode $generics $this => $field: $inner; $mode); )+
74 };
75
76 (@mode [$($generic:tt)*] $this:ty => $field:tt : $inner:ty; owned) => {
77 impl<$($generic)*> ::core::iter::IntoIterator for $this
78 where
79 $inner: ::core::iter::IntoIterator,
80 {
81 type Item = <$inner as ::core::iter::IntoIterator>::Item;
82 type IntoIter = <$inner as ::core::iter::IntoIterator>::IntoIter;
83
84 fn into_iter(self) -> Self::IntoIter {
85 <$inner as ::core::iter::IntoIterator>::into_iter(self.$field)
86 }
87 }
88 };
89
90 (@mode [$($generic:tt)*] $this:ty => $field:tt : $inner:ty; ref) => {
91 impl<'__impl_more_iter, $($generic)*> ::core::iter::IntoIterator for &'__impl_more_iter $this
92 where
93 $inner: '__impl_more_iter,
94 &'__impl_more_iter $inner: ::core::iter::IntoIterator,
95 {
96 type Item = <&'__impl_more_iter $inner as ::core::iter::IntoIterator>::Item;
97 type IntoIter = <&'__impl_more_iter $inner as ::core::iter::IntoIterator>::IntoIter;
98
99 fn into_iter(self) -> Self::IntoIter {
100 <&'__impl_more_iter $inner as ::core::iter::IntoIterator>::into_iter(&self.$field)
101 }
102 }
103 };
104
105 (@mode [$($generic:tt)*] $this:ty => $field:tt : $inner:ty; ref_mut) => {
106 impl<'__impl_more_iter, $($generic)*> ::core::iter::IntoIterator for &'__impl_more_iter mut $this
107 where
108 $inner: '__impl_more_iter,
109 &'__impl_more_iter mut $inner: ::core::iter::IntoIterator,
110 {
111 type Item = <&'__impl_more_iter mut $inner as ::core::iter::IntoIterator>::Item;
112 type IntoIter = <&'__impl_more_iter mut $inner as ::core::iter::IntoIterator>::IntoIter;
113
114 fn into_iter(self) -> Self::IntoIter {
115 <&'__impl_more_iter mut $inner as ::core::iter::IntoIterator>::into_iter(&mut self.$field)
116 }
117 }
118 };
119
120 (@mode $generics:tt $this:ty => $field:tt : $inner:ty; $mode:ident) => {
121 ::core::compile_error!("expected iteration mode `owned`, `ref`, or `ref_mut`");
122 };
123}
124
125#[macro_export]
155macro_rules! forward_from_iterator {
156 (<$($generic:ident),+> in $($rest:tt)+) => {
157 $crate::forward_from_iterator!(@impl [$($generic),+] $($rest)+);
158 };
159
160 (<const $($rest:tt)+) => {
161 $crate::__impl_more_parse_generics!(@parse forward_from_iterator [] [] const $($rest)+);
162 };
163
164 (<$generic:ident, $($rest:tt)+) => {
165 $crate::__impl_more_parse_generics!(@parse forward_from_iterator [] [] $generic, $($rest)+);
166 };
167
168 (@impl [$($generic:tt)+] $this:ty => $inner:ty $(,)?) => {
169 $crate::forward_from_iterator!(@impl [$($generic)+] $this => 0: $inner);
170 };
171
172 ($this:ty => $field:tt : $inner:ty $(,)?) => {
173 $crate::forward_from_iterator!(@impl [] $this => $field: $inner);
174 };
175
176 ($this:ty => $inner:ty $(,)?) => {
177 $crate::forward_from_iterator!(@impl [] $this => 0: $inner);
178 };
179
180 (@impl [$($generic:tt)*] $this:ty => $field:tt : $inner:ty $(,)?) => {
181 impl<__ImplMoreItem, $($generic)*> ::core::iter::FromIterator<__ImplMoreItem> for $this
182 where
183 $inner: ::core::iter::FromIterator<__ImplMoreItem>,
184 {
185 fn from_iter<__ImplMoreIter: ::core::iter::IntoIterator<Item = __ImplMoreItem>>(iter: __ImplMoreIter) -> Self {
186 Self { $field: <$inner as ::core::iter::FromIterator<__ImplMoreItem>>::from_iter(iter) }
187 }
188 }
189 };
190}
191
192#[macro_export]
223macro_rules! forward_extend {
224 (<$($generic:ident),+> in $($rest:tt)+) => {
225 $crate::forward_extend!(@impl [$($generic),+] $($rest)+);
226 };
227
228 (<const $($rest:tt)+) => {
229 $crate::__impl_more_parse_generics!(@parse forward_extend [] [] const $($rest)+);
230 };
231
232 (<$generic:ident, $($rest:tt)+) => {
233 $crate::__impl_more_parse_generics!(@parse forward_extend [] [] $generic, $($rest)+);
234 };
235
236 (@impl [$($generic:tt)+] $this:ty => $inner:ty $(,)?) => {
237 $crate::forward_extend!(@impl [$($generic)+] $this => 0: $inner);
238 };
239
240 ($this:ty => $field:tt : $inner:ty $(,)?) => {
241 $crate::forward_extend!(@impl [] $this => $field: $inner);
242 };
243
244 ($this:ty => $inner:ty $(,)?) => {
245 $crate::forward_extend!(@impl [] $this => 0: $inner);
246 };
247
248 (@impl [$($generic:tt)*] $this:ty => $field:tt : $inner:ty $(,)?) => {
249 impl<__ImplMoreItem, $($generic)*> ::core::iter::Extend<__ImplMoreItem> for $this
250 where
251 $inner: ::core::iter::Extend<__ImplMoreItem>,
252 {
253 fn extend<__ImplMoreIter: ::core::iter::IntoIterator<Item = __ImplMoreItem>>(&mut self, iter: __ImplMoreIter) {
254 <$inner as ::core::iter::Extend<__ImplMoreItem>>::extend(&mut self.$field, iter);
255 }
256 }
257 };
258}
259
260#[cfg(test)]
261mod tests {
262 use alloc::{string::String, vec, vec::Vec};
263
264 struct Items<T>(Vec<T>);
265 crate::forward_into_iterator!(<T> in Items<T> => Vec<T>; owned, ref, ref_mut,);
266 crate::forward_from_iterator!(<T> in Items<T> => Vec<T>,);
267 crate::forward_extend!(<T> in Items<T> => Vec<T>,);
268
269 #[test]
270 fn collect_extend_and_iterate_non_copy_items() {
271 let mut items = IntoIterator::into_iter([String::from("a")]).collect::<Items<_>>();
272 items.extend([String::from("b")]);
273 for item in &mut items {
274 item.push('!');
275 }
276 assert_eq!(
277 (&items).into_iter().map(String::as_str).collect::<Vec<_>>(),
278 ["a!", "b!"]
279 );
280 assert_eq!(items.into_iter().collect::<Vec<_>>(), ["a!", "b!"]);
281 }
282
283 #[test]
284 fn generic_named_field_and_borrowed_items() {
285 struct Named<T> {
286 values: Vec<T>,
287 }
288 crate::forward_into_iterator!(<T> in Named<T> => values: Vec<T>; ref_mut, owned, ref);
289 crate::forward_from_iterator!(<T> in Named<T> => values: Vec<T>);
290 crate::forward_extend!(<T> in Named<T> => values: Vec<T>);
291 let source = vec![String::from("a")];
292 let mut items = source.iter().collect::<Named<_>>();
293 items.extend(source.iter());
294 for item in &mut items {
295 assert_eq!(*item, &source[0]);
296 }
297 assert_eq!((&items).into_iter().count(), 2);
298 assert_eq!(
299 items.into_iter().collect::<Vec<_>>(),
300 [&source[0], &source[0]]
301 );
302 }
303
304 #[test]
305 fn concrete_named_field() {
306 struct Named {
307 values: Vec<u8>,
308 }
309 crate::forward_into_iterator!(Named => values: Vec<u8>; owned, ref, ref_mut);
310 crate::forward_from_iterator!(Named => values: Vec<u8>);
311 crate::forward_extend!(Named => values: Vec<u8>);
312 let mut items = (0..2).collect::<Named>();
313 items.extend([2]);
314 for item in &mut items {
315 *item += 1;
316 }
317 assert_eq!((&items).into_iter().copied().collect::<Vec<_>>(), [1, 2, 3]);
318 assert_eq!(items.into_iter().collect::<Vec<_>>(), [1, 2, 3]);
319 }
320
321 #[test]
322 fn concrete_tuple_and_empty_input() {
323 struct Bytes(Vec<u8>);
324 crate::forward_into_iterator!(Bytes => Vec<u8>; owned, ref, ref_mut);
325 crate::forward_from_iterator!(Bytes => Vec<u8>);
326 crate::forward_extend!(Bytes => Vec<u8>);
327 let mut bytes = core::iter::empty::<u8>().collect::<Bytes>();
328 bytes.extend(core::iter::empty::<u8>());
329 assert_eq!((&bytes).into_iter().next(), None);
330 assert_eq!((&mut bytes).into_iter().next(), None);
331 assert_eq!(bytes.into_iter().next(), None);
332 }
333
334 #[test]
335 fn collection_without_into_iterator_accepts_multiple_item_types() {
336 struct Text(String);
337 crate::forward_from_iterator!(Text => String);
338 crate::forward_extend!(Text => String);
339 let mut text = ['a', 'b'].iter().copied().collect::<Text>();
340 text.extend(["cd", "ef"]);
341 text.extend(['g']);
342 assert_eq!(text.0, "abcdefg");
343 assert_eq!(["ab", "cd"].iter().copied().collect::<Text>().0, "abcd");
344 }
345
346 #[test]
347 fn modes_are_opt_in_and_bounds_apply_to_the_collection() {
348 struct Shared<T>(T);
349 crate::forward_into_iterator!(<T> in Shared<T> => T; ref);
350 static_assertions::assert_not_impl_any!(Shared<Vec<u8>>: IntoIterator);
351 static_assertions::assert_not_impl_any!(&mut Shared<Vec<u8>>: IntoIterator);
352 assert_eq!(
353 (&Shared(vec![1, 2]))
354 .into_iter()
355 .copied()
356 .collect::<Vec<_>>(),
357 [1, 2]
358 );
359
360 struct Owned<T>(T);
361 crate::forward_into_iterator!(<T> in Owned<T> => T; owned);
362 static_assertions::assert_not_impl_any!(&Owned<Vec<u8>>: IntoIterator);
363 static_assertions::assert_not_impl_any!(&mut Owned<Vec<u8>>: IntoIterator);
364 assert_eq!(Owned(0..3).into_iter().sum::<u8>(), 3);
365 }
366}