Skip to main content

impl_more/
iter.rs

1/// Implement [`IntoIterator`] by forwarding to a field.
2///
3/// Select one or more modes: `owned` for `Self`, `ref` for `&Self`, and `ref_mut`
4/// for `&mut Self`. Each mode uses the inner type's item and iterator types.
5/// Only the selected modes are implemented. Emitted code supports `no_std`.
6///
7/// Declare type and const parameters before `in`.
8///
9/// # Examples
10///
11/// ```
12/// struct Items<T>(Vec<T>);
13///
14/// impl_more::forward_into_iterator!(<T> in Items<T> => Vec<T>; owned, ref, ref_mut);
15///
16/// let mut items = Items(vec![1, 2]);
17/// for item in &mut items { *item += 1; }
18///
19/// assert_eq!((&items).into_iter().copied().collect::<Vec<_>>(), vec![2, 3]);
20/// assert_eq!(items.into_iter().collect::<Vec<_>>(), vec![2, 3]);
21/// ```
22///
23/// Select a named field with `=> field: InnerType`:
24///
25/// ```
26/// struct Items { values: Vec<u8> }
27///
28/// impl_more::forward_into_iterator!(Items => values: Vec<u8>; ref);
29///
30/// assert_eq!((&Items { values: vec![1] }).into_iter().next(), Some(&1));
31/// ```
32///
33/// With type and const parameters:
34/// ```
35/// struct Array<T, const N: usize>([T; N]);
36/// impl_more::forward_into_iterator!(
37///     <T, const N: usize> in Array<T, N> => [T; N]; owned, ref, ref_mut
38/// );
39///
40/// assert_eq!(Array([1, 2, 3]).into_iter().sum::<u32>(), 6);
41/// ```
42#[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/// Implement [`FromIterator`](core::iter::FromIterator) for a single-field wrapper.
126///
127/// Accept any item type supported by the inner collection's `FromIterator`
128/// implementation. The inner type does not need to implement `IntoIterator`.
129/// Emitted code supports `no_std`.
130///
131/// Declare type and const parameters before `in`.
132///
133/// # Examples
134///
135/// ```
136/// struct Items<T>(Vec<T>);
137///
138/// impl_more::forward_from_iterator!(<T> in Items<T> => Vec<T>);
139///
140/// let items = (1..4).collect::<Items<_>>();
141///
142/// assert_eq!(items.0, vec![1, 2, 3]);
143/// ```
144///
145/// ```
146/// struct Text { value: String }
147///
148/// impl_more::forward_from_iterator!(Text => value: String);
149///
150/// let text = ["hello", " world"].iter().copied().collect::<Text>();
151///
152/// assert_eq!(text.value, "hello world");
153/// ```
154#[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/// Implement [`Extend`] by forwarding to a field.
193///
194/// Accept any item type supported by the inner collection's `Extend`
195/// implementation. Emitted code supports `no_std`.
196///
197/// Declare type and const parameters before `in`.
198///
199/// # Examples
200///
201/// ```
202/// struct Items<T>(Vec<T>);
203///
204/// impl_more::forward_extend!(<T> in Items<T> => Vec<T>);
205///
206/// let mut items = Items(vec![1]);
207/// items.extend([2, 3]);
208///
209/// assert_eq!(items.0, vec![1, 2, 3]);
210/// ```
211///
212/// ```
213/// struct Text { value: String }
214///
215/// impl_more::forward_extend!(Text => value: String);
216///
217/// let mut text = Text { value: String::new() };
218/// text.extend(["hello", " world"]);
219///
220/// assert_eq!(text.value, "hello world");
221/// ```
222#[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}