]>
Commit | Line | Data |
---|---|---|
48663c56 XL |
1 | use crate::fmt; |
2 | use crate::ops::Try; | |
3 | ||
9fa01778 XL |
4 | use super::super::{Iterator, DoubleEndedIterator, FusedIterator}; |
5 | use 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")] | |
17 | pub struct FlatMap<I, U: IntoIterator, F> { | |
18 | inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter> | |
19 | } | |
20 | impl<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 |
27 | impl<I: Clone, U, F: Clone> Clone for FlatMap<I, U, F> |
28 | where | |
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 |
35 | impl<I: fmt::Debug, U, F> fmt::Debug for FlatMap<I, U, F> |
36 | where | |
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")] | |
45 | impl<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")] | |
72 | impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> | |
416331ca XL |
73 | where |
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")] | |
96 | impl<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 | 109 | pub struct Flatten<I: Iterator<Item: IntoIterator>> { |
9fa01778 XL |
110 | inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>, |
111 | } | |
416331ca XL |
112 | |
113 | impl<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")] | |
120 | impl<I, U> fmt::Debug for Flatten<I> | |
416331ca XL |
121 | where |
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")] | |
131 | impl<I, U> Clone for Flatten<I> | |
416331ca XL |
132 | where |
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")] | |
140 | impl<I, U> Iterator for Flatten<I> | |
416331ca XL |
141 | where |
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")] | |
169 | impl<I, U> DoubleEndedIterator for Flatten<I> | |
416331ca XL |
170 | where |
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")] | |
193 | impl<I, U> FusedIterator for Flatten<I> | |
416331ca XL |
194 | where |
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)] | |
202 | struct FlattenCompat<I, U> { | |
203 | iter: I, | |
204 | frontiter: Option<U>, | |
205 | backiter: Option<U>, | |
206 | } | |
207 | impl<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 | ||
214 | impl<I, U> Iterator for FlattenCompat<I, U> | |
416331ca XL |
215 | where |
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 | ||
296 | impl<I, U> DoubleEndedIterator for FlattenCompat<I, U> | |
416331ca XL |
297 | where |
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 | } |