]> git.lizzy.rs Git - rust.git/blob - library/core/src/iter/adapters/mod.rs
Split iterator adaptors into individual modules
[rust.git] / library / core / src / iter / adapters / mod.rs
1 use crate::{
2     iter::{InPlaceIterable, Iterator},
3     ops::{ControlFlow, Try},
4 };
5
6 mod chain;
7 mod cloned;
8 mod copied;
9 mod cycle;
10 mod enumerate;
11 mod filter;
12 mod filter_map;
13 mod flatten;
14 mod fuse;
15 mod inspect;
16 mod map;
17 mod map_while;
18 mod peekable;
19 mod rev;
20 mod scan;
21 mod skip;
22 mod skip_while;
23 mod step_by;
24 mod take;
25 mod take_while;
26 mod zip;
27
28 pub use self::{
29     chain::Chain,
30     cycle::Cycle,
31     enumerate::Enumerate,
32     filter::Filter,
33     filter_map::FilterMap,
34     flatten::FlatMap,
35     fuse::Fuse,
36     inspect::Inspect,
37     map::Map,
38     peekable::Peekable,
39     rev::Rev,
40     scan::Scan,
41     skip::Skip,
42     skip_while::SkipWhile,
43     take::Take,
44     take_while::TakeWhile,
45     zip::Zip,
46 };
47
48 #[stable(feature = "iter_cloned", since = "1.1.0")]
49 pub use self::cloned::Cloned;
50
51 #[stable(feature = "iterator_step_by", since = "1.28.0")]
52 pub use self::step_by::StepBy;
53
54 #[stable(feature = "iterator_flatten", since = "1.29.0")]
55 pub use self::flatten::Flatten;
56
57 #[stable(feature = "iter_copied", since = "1.36.0")]
58 pub use self::copied::Copied;
59
60 #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
61 pub use self::map_while::MapWhile;
62
63 #[unstable(feature = "trusted_random_access", issue = "none")]
64 pub use self::zip::TrustedRandomAccess;
65
66 /// This trait provides transitive access to source-stage in an interator-adapter pipeline
67 /// under the conditions that
68 /// * the iterator source `S` itself implements `SourceIter<Source = S>`
69 /// * there is a delegating implementation of this trait for each adapter in the pipeline between
70 ///   the source and the pipeline consumer.
71 ///
72 /// When the source is an owning iterator struct (commonly called `IntoIter`) then
73 /// this can be useful for specializing [`FromIterator`] implementations or recovering the
74 /// remaining elements after an iterator has been partially exhausted.
75 ///
76 /// Note that implementations do not necessarily have to provide access to the inner-most
77 /// source of a pipeline. A stateful intermediate adapter might eagerly evaluate a part
78 /// of the pipeline and expose its internal storage as source.
79 ///
80 /// The trait is unsafe because implementers must uphold additional safety properties.
81 /// See [`as_inner`] for details.
82 ///
83 /// # Examples
84 ///
85 /// Retrieving a partially consumed source:
86 ///
87 /// ```
88 /// # #![feature(inplace_iteration)]
89 /// # use std::iter::SourceIter;
90 ///
91 /// let mut iter = vec![9, 9, 9].into_iter().map(|i| i * i);
92 /// let _ = iter.next();
93 /// let mut remainder = std::mem::replace(unsafe { iter.as_inner() }, Vec::new().into_iter());
94 /// println!("n = {} elements remaining", remainder.len());
95 /// ```
96 ///
97 /// [`FromIterator`]: crate::iter::FromIterator
98 /// [`as_inner`]: SourceIter::as_inner
99 #[unstable(issue = "none", feature = "inplace_iteration")]
100 pub unsafe trait SourceIter {
101     /// A source stage in an iterator pipeline.
102     type Source: Iterator;
103
104     /// Retrieve the source of an iterator pipeline.
105     ///
106     /// # Safety
107     ///
108     /// Implementations of must return the same mutable reference for their lifetime, unless
109     /// replaced by a caller.
110     /// Callers may only replace the reference when they stopped iteration and drop the
111     /// iterator pipeline after extracting the source.
112     ///
113     /// This means iterator adapters can rely on the source not changing during
114     /// iteration but they cannot rely on it in their Drop implementations.
115     ///
116     /// Implementing this method means adapters relinquish private-only access to their
117     /// source and can only rely on guarantees made based on method receiver types.
118     /// The lack of restricted access also requires that adapters must uphold the source's
119     /// public API even when they have access to its internals.
120     ///
121     /// Callers in turn must expect the source to be in any state that is consistent with
122     /// its public API since adapters sitting between it and the source have the same
123     /// access. In particular an adapter may have consumed more elements than strictly necessary.
124     ///
125     /// The overall goal of these requirements is to let the consumer of a pipeline use
126     /// * whatever remains in the source after iteration has stopped
127     /// * the memory that has become unused by advancing a consuming iterator
128     ///
129     /// [`next()`]: Iterator::next
130     unsafe fn as_inner(&mut self) -> &mut Self::Source;
131 }
132
133 /// An iterator adapter that produces output as long as the underlying
134 /// iterator produces `Result::Ok` values.
135 ///
136 /// If an error is encountered, the iterator stops and the error is
137 /// stored.
138 pub(crate) struct ResultShunt<'a, I, E> {
139     iter: I,
140     error: &'a mut Result<(), E>,
141 }
142
143 /// Process the given iterator as if it yielded a `T` instead of a
144 /// `Result<T, _>`. Any errors will stop the inner iterator and
145 /// the overall result will be an error.
146 pub(crate) fn process_results<I, T, E, F, U>(iter: I, mut f: F) -> Result<U, E>
147 where
148     I: Iterator<Item = Result<T, E>>,
149     for<'a> F: FnMut(ResultShunt<'a, I, E>) -> U,
150 {
151     let mut error = Ok(());
152     let shunt = ResultShunt { iter, error: &mut error };
153     let value = f(shunt);
154     error.map(|()| value)
155 }
156
157 impl<I, T, E> Iterator for ResultShunt<'_, I, E>
158 where
159     I: Iterator<Item = Result<T, E>>,
160 {
161     type Item = T;
162
163     fn next(&mut self) -> Option<Self::Item> {
164         self.find(|_| true)
165     }
166
167     fn size_hint(&self) -> (usize, Option<usize>) {
168         if self.error.is_err() {
169             (0, Some(0))
170         } else {
171             let (_, upper) = self.iter.size_hint();
172             (0, upper)
173         }
174     }
175
176     fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
177     where
178         F: FnMut(B, Self::Item) -> R,
179         R: Try<Ok = B>,
180     {
181         let error = &mut *self.error;
182         self.iter
183             .try_fold(init, |acc, x| match x {
184                 Ok(x) => ControlFlow::from_try(f(acc, x)),
185                 Err(e) => {
186                     *error = Err(e);
187                     ControlFlow::Break(try { acc })
188                 }
189             })
190             .into_try()
191     }
192
193     fn fold<B, F>(mut self, init: B, fold: F) -> B
194     where
195         Self: Sized,
196         F: FnMut(B, Self::Item) -> B,
197     {
198         #[inline]
199         fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
200             move |acc, x| Ok(f(acc, x))
201         }
202
203         self.try_fold(init, ok(fold)).unwrap()
204     }
205 }