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