Skip to main content

const_size_flatten/
flatten.rs

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