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