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