Skip to main content

const_size_flatten/
flatmap.rs

1use crate::{flatten_base::ConstSizeFlattenBase, ConstSizeIntoIterator};
2use core::{
3    fmt::Debug,
4    iter::{FusedIterator, Map},
5};
6
7/// A version of [`FlatMap`] that knows its inner iterators’ size in advance,
8/// and can produce accurate lower and upper bounds using [`Iterator::size_hint`].
9/// This iterator does not require [`ExactSizeIterator`] for the inner iterators.
10/// It can nonetheless provide an accurate length via [`Iterator::size_hint`] if they implement it.
11/// This iterator does not implement [`ExactSizeIterator`], even if the inner iterators implement it.
12/// This is because the nesting may cause the size to exceed [`usize::MAX`].
13///
14/// [`FlatMap`]: core::iter::FlatMap
15pub struct ConstSizeFlatMap<I, U: IntoIterator, F> {
16    inner: ConstSizeFlattenBase<Map<I, F>, U::IntoIter>,
17}
18
19impl<I, U, F> ConstSizeFlatMap<I, U, F>
20where
21    I: Iterator,
22    U: IntoIterator,
23    F: FnMut(I::Item) -> U,
24{
25    /// Construct a [`ConstSizeFlatMap`] from an [`IntoIterator`] (which includes [`Iterator`]s).
26    fn new<J: IntoIterator<IntoIter = I>>(iter: J, f: F) -> Self {
27        Self {
28            inner: ConstSizeFlattenBase::new(iter.into_iter().map(f)),
29        }
30    }
31}
32
33/// Construct a [`ConstSizeFlatMap`] from an [`IntoIterator`] (which includes [`Iterator`]s).
34pub fn const_size_flat_map<I, U, F>(iter: I, f: F) -> ConstSizeFlatMap<I::IntoIter, U, F>
35where
36    I: IntoIterator,
37    U: IntoIterator,
38    F: FnMut(I::Item) -> U,
39{
40    ConstSizeFlatMap::new(iter, f)
41}
42
43impl<I, U, F> Clone for ConstSizeFlatMap<I, U, F>
44where
45    I: Clone,
46    F: Clone,
47    U: IntoIterator,
48    U::IntoIter: Clone,
49{
50    fn clone(&self) -> Self {
51        ConstSizeFlatMap {
52            inner: self.inner.clone(),
53        }
54    }
55}
56
57impl<I, U, F> Debug for ConstSizeFlatMap<I, U, F>
58where
59    I: Debug,
60    U: IntoIterator,
61    U::IntoIter: Debug,
62{
63    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
64        f.debug_struct("ConstSizeFlatMap")
65            .field("inner", &self.inner)
66            .finish()
67    }
68}
69
70impl<I, U, F> Iterator for ConstSizeFlatMap<I, U, F>
71where
72    I: Iterator,
73    F: FnMut(I::Item) -> U,
74    U: ConstSizeIntoIterator,
75{
76    type Item = U::Item;
77    fn next(&mut self) -> Option<Self::Item> {
78        self.inner.next()
79    }
80    fn size_hint(&self) -> (usize, Option<usize>) {
81        self.inner.size_hint()
82    }
83}
84
85impl<I, U, F> DoubleEndedIterator for ConstSizeFlatMap<I, U, F>
86where
87    I: DoubleEndedIterator,
88    F: FnMut(I::Item) -> U,
89    U: ConstSizeIntoIterator,
90    U::IntoIter: DoubleEndedIterator,
91{
92    fn next_back(&mut self) -> Option<Self::Item> {
93        self.inner.next_back()
94    }
95}
96
97impl<I, U, F> FusedIterator for ConstSizeFlatMap<I, U, F>
98where
99    I: Iterator,
100    F: FnMut(I::Item) -> U,
101    U: ConstSizeIntoIterator,
102{
103}