core/iter/adapters/
mod.rs

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