1#[macro_export]
31macro_rules! forward_into_iterator {
32 (<$($generic:ident),+> in $this:ty => $field:tt : $inner:ty; $($mode:ident),+ $(,)?) => {
33 $crate::forward_into_iterator!(@modes [$($generic),+] $this => $field: $inner; $($mode),+);
34 };
35 (<$($generic:ident),+> in $this:ty => $inner:ty; $($mode:ident),+ $(,)?) => {
36 $crate::forward_into_iterator!(@modes [$($generic),+] $this => 0: $inner; $($mode),+);
37 };
38 ($this:ty => $field:tt : $inner:ty; $($mode:ident),+ $(,)?) => {
39 $crate::forward_into_iterator!(@modes [] $this => $field: $inner; $($mode),+);
40 };
41 ($this:ty => $inner:ty; $($mode:ident),+ $(,)?) => {
42 $crate::forward_into_iterator!(@modes [] $this => 0: $inner; $($mode),+);
43 };
44 (@modes $generics:tt $this:ty => $field:tt : $inner:ty; $($mode:ident),+) => {
45 $( $crate::forward_into_iterator!(@mode $generics $this => $field: $inner; $mode); )+
46 };
47 (@mode [$($generic:ident),*] $this:ty => $field:tt : $inner:ty; owned) => {
48 impl<$($generic),*> ::core::iter::IntoIterator for $this
49 where
50 $inner: ::core::iter::IntoIterator,
51 {
52 type Item = <$inner as ::core::iter::IntoIterator>::Item;
53 type IntoIter = <$inner as ::core::iter::IntoIterator>::IntoIter;
54
55 fn into_iter(self) -> Self::IntoIter {
56 <$inner as ::core::iter::IntoIterator>::into_iter(self.$field)
57 }
58 }
59 };
60 (@mode [$($generic:ident),*] $this:ty => $field:tt : $inner:ty; ref) => {
61 impl<'__impl_more_iter, $($generic),*> ::core::iter::IntoIterator for &'__impl_more_iter $this
62 where
63 $inner: '__impl_more_iter,
64 &'__impl_more_iter $inner: ::core::iter::IntoIterator,
65 {
66 type Item = <&'__impl_more_iter $inner as ::core::iter::IntoIterator>::Item;
67 type IntoIter = <&'__impl_more_iter $inner as ::core::iter::IntoIterator>::IntoIter;
68
69 fn into_iter(self) -> Self::IntoIter {
70 <&'__impl_more_iter $inner as ::core::iter::IntoIterator>::into_iter(&self.$field)
71 }
72 }
73 };
74 (@mode [$($generic:ident),*] $this:ty => $field:tt : $inner:ty; ref_mut) => {
75 impl<'__impl_more_iter, $($generic),*> ::core::iter::IntoIterator for &'__impl_more_iter mut $this
76 where
77 $inner: '__impl_more_iter,
78 &'__impl_more_iter mut $inner: ::core::iter::IntoIterator,
79 {
80 type Item = <&'__impl_more_iter mut $inner as ::core::iter::IntoIterator>::Item;
81 type IntoIter = <&'__impl_more_iter mut $inner as ::core::iter::IntoIterator>::IntoIter;
82
83 fn into_iter(self) -> Self::IntoIter {
84 <&'__impl_more_iter mut $inner as ::core::iter::IntoIterator>::into_iter(&mut self.$field)
85 }
86 }
87 };
88 (@mode $generics:tt $this:ty => $field:tt : $inner:ty; $mode:ident) => {
89 ::core::compile_error!("expected iteration mode `owned`, `ref`, or `ref_mut`");
90 };
91}
92
93#[macro_export]
121macro_rules! forward_from_iterator {
122 (<$($generic:ident),+> in $this:ty => $field:tt : $inner:ty $(,)?) => {
123 $crate::forward_from_iterator!(@impl [$($generic),+] $this => $field: $inner);
124 };
125 (<$($generic:ident),+> in $this:ty => $inner:ty $(,)?) => {
126 $crate::forward_from_iterator!(@impl [$($generic),+] $this => 0: $inner);
127 };
128 ($this:ty => $field:tt : $inner:ty $(,)?) => {
129 $crate::forward_from_iterator!(@impl [] $this => $field: $inner);
130 };
131 ($this:ty => $inner:ty $(,)?) => {
132 $crate::forward_from_iterator!(@impl [] $this => 0: $inner);
133 };
134 (@impl [$($generic:ident),*] $this:ty => $field:tt : $inner:ty) => {
135 impl<__ImplMoreItem, $($generic),*> ::core::iter::FromIterator<__ImplMoreItem> for $this
136 where
137 $inner: ::core::iter::FromIterator<__ImplMoreItem>,
138 {
139 fn from_iter<__ImplMoreIter: ::core::iter::IntoIterator<Item = __ImplMoreItem>>(iter: __ImplMoreIter) -> Self {
140 Self { $field: <$inner as ::core::iter::FromIterator<__ImplMoreItem>>::from_iter(iter) }
141 }
142 }
143 };
144}
145
146#[macro_export]
175macro_rules! forward_extend {
176 (<$($generic:ident),+> in $this:ty => $field:tt : $inner:ty $(,)?) => {
177 $crate::forward_extend!(@impl [$($generic),+] $this => $field: $inner);
178 };
179 (<$($generic:ident),+> in $this:ty => $inner:ty $(,)?) => {
180 $crate::forward_extend!(@impl [$($generic),+] $this => 0: $inner);
181 };
182 ($this:ty => $field:tt : $inner:ty $(,)?) => {
183 $crate::forward_extend!(@impl [] $this => $field: $inner);
184 };
185 ($this:ty => $inner:ty $(,)?) => {
186 $crate::forward_extend!(@impl [] $this => 0: $inner);
187 };
188 (@impl [$($generic:ident),*] $this:ty => $field:tt : $inner:ty) => {
189 impl<__ImplMoreItem, $($generic),*> ::core::iter::Extend<__ImplMoreItem> for $this
190 where
191 $inner: ::core::iter::Extend<__ImplMoreItem>,
192 {
193 fn extend<__ImplMoreIter: ::core::iter::IntoIterator<Item = __ImplMoreItem>>(&mut self, iter: __ImplMoreIter) {
194 <$inner as ::core::iter::Extend<__ImplMoreItem>>::extend(&mut self.$field, iter);
195 }
196 }
197 };
198}
199
200#[cfg(test)]
201mod tests {
202 use alloc::{string::String, vec, vec::Vec};
203
204 struct Items<T>(Vec<T>);
205 crate::forward_into_iterator!(<T> in Items<T> => Vec<T>; owned, ref, ref_mut,);
206 crate::forward_from_iterator!(<T> in Items<T> => Vec<T>,);
207 crate::forward_extend!(<T> in Items<T> => Vec<T>,);
208
209 #[test]
210 fn collect_extend_and_iterate_non_copy_items() {
211 let mut items = IntoIterator::into_iter([String::from("a")]).collect::<Items<_>>();
212 items.extend([String::from("b")]);
213 for item in &mut items {
214 item.push('!');
215 }
216 assert_eq!(
217 (&items).into_iter().map(String::as_str).collect::<Vec<_>>(),
218 ["a!", "b!"]
219 );
220 assert_eq!(items.into_iter().collect::<Vec<_>>(), ["a!", "b!"]);
221 }
222
223 #[test]
224 fn generic_named_field_and_borrowed_items() {
225 struct Named<T> {
226 values: Vec<T>,
227 }
228 crate::forward_into_iterator!(<T> in Named<T> => values: Vec<T>; ref_mut, owned, ref);
229 crate::forward_from_iterator!(<T> in Named<T> => values: Vec<T>);
230 crate::forward_extend!(<T> in Named<T> => values: Vec<T>);
231 let source = vec![String::from("a")];
232 let mut items = source.iter().collect::<Named<_>>();
233 items.extend(source.iter());
234 for item in &mut items {
235 assert_eq!(*item, &source[0]);
236 }
237 assert_eq!((&items).into_iter().count(), 2);
238 assert_eq!(
239 items.into_iter().collect::<Vec<_>>(),
240 [&source[0], &source[0]]
241 );
242 }
243
244 #[test]
245 fn concrete_named_field() {
246 struct Named {
247 values: Vec<u8>,
248 }
249 crate::forward_into_iterator!(Named => values: Vec<u8>; owned, ref, ref_mut);
250 crate::forward_from_iterator!(Named => values: Vec<u8>);
251 crate::forward_extend!(Named => values: Vec<u8>);
252 let mut items = (0..2).collect::<Named>();
253 items.extend([2]);
254 for item in &mut items {
255 *item += 1;
256 }
257 assert_eq!((&items).into_iter().copied().collect::<Vec<_>>(), [1, 2, 3]);
258 assert_eq!(items.into_iter().collect::<Vec<_>>(), [1, 2, 3]);
259 }
260
261 #[test]
262 fn concrete_tuple_and_empty_input() {
263 struct Bytes(Vec<u8>);
264 crate::forward_into_iterator!(Bytes => Vec<u8>; owned, ref, ref_mut);
265 crate::forward_from_iterator!(Bytes => Vec<u8>);
266 crate::forward_extend!(Bytes => Vec<u8>);
267 let mut bytes = core::iter::empty::<u8>().collect::<Bytes>();
268 bytes.extend(core::iter::empty::<u8>());
269 assert_eq!((&bytes).into_iter().next(), None);
270 assert_eq!((&mut bytes).into_iter().next(), None);
271 assert_eq!(bytes.into_iter().next(), None);
272 }
273
274 #[test]
275 fn collection_without_into_iterator_accepts_multiple_item_types() {
276 struct Text(String);
277 crate::forward_from_iterator!(Text => String);
278 crate::forward_extend!(Text => String);
279 let mut text = ['a', 'b'].iter().copied().collect::<Text>();
280 text.extend(["cd", "ef"]);
281 text.extend(['g']);
282 assert_eq!(text.0, "abcdefg");
283 assert_eq!(["ab", "cd"].iter().copied().collect::<Text>().0, "abcd");
284 }
285
286 #[test]
287 fn modes_are_opt_in_and_bounds_apply_to_the_collection() {
288 struct Shared<T>(T);
289 crate::forward_into_iterator!(<T> in Shared<T> => T; ref);
290 static_assertions::assert_not_impl_any!(Shared<Vec<u8>>: IntoIterator);
291 static_assertions::assert_not_impl_any!(&mut Shared<Vec<u8>>: IntoIterator);
292 assert_eq!(
293 (&Shared(vec![1, 2]))
294 .into_iter()
295 .copied()
296 .collect::<Vec<_>>(),
297 [1, 2]
298 );
299
300 struct Owned<T>(T);
301 crate::forward_into_iterator!(<T> in Owned<T> => T; owned);
302 static_assertions::assert_not_impl_any!(&Owned<Vec<u8>>: IntoIterator);
303 static_assertions::assert_not_impl_any!(&mut Owned<Vec<u8>>: IntoIterator);
304 assert_eq!(Owned(0..3).into_iter().sum::<u8>(), 3);
305 }
306}