Skip to content

Commit fb974df

Browse files
author
Clar Fon
committed
Move Flatten and FlatMap to own module
1 parent ebfd083 commit fb974df

File tree

2 files changed

+321
-313
lines changed

2 files changed

+321
-313
lines changed

src/libcore/iter/adapters/flatten.rs

Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
use fmt;
2+
use ops::Try;
3+
use super::super::{Iterator, DoubleEndedIterator, FusedIterator};
4+
use super::Map;
5+
6+
/// An iterator that maps each element to an iterator, and yields the elements
7+
/// of the produced iterators.
8+
///
9+
/// This `struct` is created by the [`flat_map`] method on [`Iterator`]. See its
10+
/// documentation for more.
11+
///
12+
/// [`flat_map`]: trait.Iterator.html#method.flat_map
13+
/// [`Iterator`]: trait.Iterator.html
14+
#[must_use = "iterators are lazy and do nothing unless consumed"]
15+
#[stable(feature = "rust1", since = "1.0.0")]
16+
pub struct FlatMap<I, U: IntoIterator, F> {
17+
pub(in super::super) inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>
18+
}
19+
20+
#[stable(feature = "rust1", since = "1.0.0")]
21+
impl<I: Clone, U: Clone + IntoIterator, F: Clone> Clone for FlatMap<I, U, F>
22+
where <U as IntoIterator>::IntoIter: Clone
23+
{
24+
fn clone(&self) -> Self { FlatMap { inner: self.inner.clone() } }
25+
}
26+
27+
#[stable(feature = "core_impl_debug", since = "1.9.0")]
28+
impl<I: fmt::Debug, U: IntoIterator, F> fmt::Debug for FlatMap<I, U, F>
29+
where U::IntoIter: fmt::Debug
30+
{
31+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32+
f.debug_struct("FlatMap").field("inner", &self.inner).finish()
33+
}
34+
}
35+
36+
#[stable(feature = "rust1", since = "1.0.0")]
37+
impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
38+
where F: FnMut(I::Item) -> U,
39+
{
40+
type Item = U::Item;
41+
42+
#[inline]
43+
fn next(&mut self) -> Option<U::Item> { self.inner.next() }
44+
45+
#[inline]
46+
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
47+
48+
#[inline]
49+
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
50+
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
51+
{
52+
self.inner.try_fold(init, fold)
53+
}
54+
55+
#[inline]
56+
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
57+
where Fold: FnMut(Acc, Self::Item) -> Acc,
58+
{
59+
self.inner.fold(init, fold)
60+
}
61+
}
62+
63+
#[stable(feature = "rust1", since = "1.0.0")]
64+
impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
65+
where F: FnMut(I::Item) -> U,
66+
U: IntoIterator,
67+
U::IntoIter: DoubleEndedIterator
68+
{
69+
#[inline]
70+
fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }
71+
72+
#[inline]
73+
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
74+
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
75+
{
76+
self.inner.try_rfold(init, fold)
77+
}
78+
79+
#[inline]
80+
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
81+
where Fold: FnMut(Acc, Self::Item) -> Acc,
82+
{
83+
self.inner.rfold(init, fold)
84+
}
85+
}
86+
87+
#[stable(feature = "fused", since = "1.26.0")]
88+
impl<I, U, F> FusedIterator for FlatMap<I, U, F>
89+
where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {}
90+
91+
/// An iterator that flattens one level of nesting in an iterator of things
92+
/// that can be turned into iterators.
93+
///
94+
/// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its
95+
/// documentation for more.
96+
///
97+
/// [`flatten`]: trait.Iterator.html#method.flatten
98+
/// [`Iterator`]: trait.Iterator.html
99+
#[must_use = "iterators are lazy and do nothing unless consumed"]
100+
#[stable(feature = "iterator_flatten", since = "1.29.0")]
101+
pub struct Flatten<I: Iterator>
102+
where I::Item: IntoIterator {
103+
pub(in super::super) inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
104+
}
105+
106+
#[stable(feature = "iterator_flatten", since = "1.29.0")]
107+
impl<I, U> fmt::Debug for Flatten<I>
108+
where I: Iterator + fmt::Debug, U: Iterator + fmt::Debug,
109+
I::Item: IntoIterator<IntoIter = U, Item = U::Item>,
110+
{
111+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112+
f.debug_struct("Flatten").field("inner", &self.inner).finish()
113+
}
114+
}
115+
116+
#[stable(feature = "iterator_flatten", since = "1.29.0")]
117+
impl<I, U> Clone for Flatten<I>
118+
where I: Iterator + Clone, U: Iterator + Clone,
119+
I::Item: IntoIterator<IntoIter = U, Item = U::Item>,
120+
{
121+
fn clone(&self) -> Self { Flatten { inner: self.inner.clone() } }
122+
}
123+
124+
#[stable(feature = "iterator_flatten", since = "1.29.0")]
125+
impl<I, U> Iterator for Flatten<I>
126+
where I: Iterator, U: Iterator,
127+
I::Item: IntoIterator<IntoIter = U, Item = U::Item>
128+
{
129+
type Item = U::Item;
130+
131+
#[inline]
132+
fn next(&mut self) -> Option<U::Item> { self.inner.next() }
133+
134+
#[inline]
135+
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
136+
137+
#[inline]
138+
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
139+
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
140+
{
141+
self.inner.try_fold(init, fold)
142+
}
143+
144+
#[inline]
145+
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
146+
where Fold: FnMut(Acc, Self::Item) -> Acc,
147+
{
148+
self.inner.fold(init, fold)
149+
}
150+
}
151+
152+
#[stable(feature = "iterator_flatten", since = "1.29.0")]
153+
impl<I, U> DoubleEndedIterator for Flatten<I>
154+
where I: DoubleEndedIterator, U: DoubleEndedIterator,
155+
I::Item: IntoIterator<IntoIter = U, Item = U::Item>
156+
{
157+
#[inline]
158+
fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }
159+
160+
#[inline]
161+
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
162+
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
163+
{
164+
self.inner.try_rfold(init, fold)
165+
}
166+
167+
#[inline]
168+
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
169+
where Fold: FnMut(Acc, Self::Item) -> Acc,
170+
{
171+
self.inner.rfold(init, fold)
172+
}
173+
}
174+
175+
#[stable(feature = "iterator_flatten", since = "1.29.0")]
176+
impl<I, U> FusedIterator for Flatten<I>
177+
where I: FusedIterator, U: Iterator,
178+
I::Item: IntoIterator<IntoIter = U, Item = U::Item> {}
179+
180+
/// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
181+
pub(in super::super) fn flatten_compat<I, U>(iter: I) -> FlattenCompat<I, U> {
182+
FlattenCompat { iter, frontiter: None, backiter: None }
183+
}
184+
185+
/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
186+
/// this type.
187+
#[derive(Clone, Debug)]
188+
pub(in super::super) struct FlattenCompat<I, U> {
189+
iter: I,
190+
frontiter: Option<U>,
191+
backiter: Option<U>,
192+
}
193+
194+
impl<I, U> Iterator for FlattenCompat<I, U>
195+
where I: Iterator, U: Iterator,
196+
I::Item: IntoIterator<IntoIter = U, Item = U::Item>
197+
{
198+
type Item = U::Item;
199+
200+
#[inline]
201+
fn next(&mut self) -> Option<U::Item> {
202+
loop {
203+
if let Some(ref mut inner) = self.frontiter {
204+
if let elt@Some(_) = inner.next() { return elt }
205+
}
206+
match self.iter.next() {
207+
None => return self.backiter.as_mut().and_then(|it| it.next()),
208+
Some(inner) => self.frontiter = Some(inner.into_iter()),
209+
}
210+
}
211+
}
212+
213+
#[inline]
214+
fn size_hint(&self) -> (usize, Option<usize>) {
215+
let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), |it| it.size_hint());
216+
let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), |it| it.size_hint());
217+
let lo = flo.saturating_add(blo);
218+
match (self.iter.size_hint(), fhi, bhi) {
219+
((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
220+
_ => (lo, None)
221+
}
222+
}
223+
224+
#[inline]
225+
fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
226+
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
227+
{
228+
if let Some(ref mut front) = self.frontiter {
229+
init = front.try_fold(init, &mut fold)?;
230+
}
231+
self.frontiter = None;
232+
233+
{
234+
let frontiter = &mut self.frontiter;
235+
init = self.iter.try_fold(init, |acc, x| {
236+
let mut mid = x.into_iter();
237+
let r = mid.try_fold(acc, &mut fold);
238+
*frontiter = Some(mid);
239+
r
240+
})?;
241+
}
242+
self.frontiter = None;
243+
244+
if let Some(ref mut back) = self.backiter {
245+
init = back.try_fold(init, &mut fold)?;
246+
}
247+
self.backiter = None;
248+
249+
Try::from_ok(init)
250+
}
251+
252+
#[inline]
253+
fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
254+
where Fold: FnMut(Acc, Self::Item) -> Acc,
255+
{
256+
self.frontiter.into_iter()
257+
.chain(self.iter.map(IntoIterator::into_iter))
258+
.chain(self.backiter)
259+
.fold(init, |acc, iter| iter.fold(acc, &mut fold))
260+
}
261+
}
262+
263+
impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
264+
where I: DoubleEndedIterator, U: DoubleEndedIterator,
265+
I::Item: IntoIterator<IntoIter = U, Item = U::Item>
266+
{
267+
#[inline]
268+
fn next_back(&mut self) -> Option<U::Item> {
269+
loop {
270+
if let Some(ref mut inner) = self.backiter {
271+
if let elt@Some(_) = inner.next_back() { return elt }
272+
}
273+
match self.iter.next_back() {
274+
None => return self.frontiter.as_mut().and_then(|it| it.next_back()),
275+
next => self.backiter = next.map(IntoIterator::into_iter),
276+
}
277+
}
278+
}
279+
280+
#[inline]
281+
fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
282+
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
283+
{
284+
if let Some(ref mut back) = self.backiter {
285+
init = back.try_rfold(init, &mut fold)?;
286+
}
287+
self.backiter = None;
288+
289+
{
290+
let backiter = &mut self.backiter;
291+
init = self.iter.try_rfold(init, |acc, x| {
292+
let mut mid = x.into_iter();
293+
let r = mid.try_rfold(acc, &mut fold);
294+
*backiter = Some(mid);
295+
r
296+
})?;
297+
}
298+
self.backiter = None;
299+
300+
if let Some(ref mut front) = self.frontiter {
301+
init = front.try_rfold(init, &mut fold)?;
302+
}
303+
self.frontiter = None;
304+
305+
Try::from_ok(init)
306+
}
307+
308+
#[inline]
309+
fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
310+
where Fold: FnMut(Acc, Self::Item) -> Acc,
311+
{
312+
self.frontiter.into_iter()
313+
.chain(self.iter.map(IntoIterator::into_iter))
314+
.chain(self.backiter)
315+
.rfold(init, |acc, iter| iter.rfold(acc, &mut fold))
316+
}
317+
}
318+

0 commit comments

Comments
 (0)