1 use crate::const_closure::ConstFnMutClosure;
2 use crate::iter::{InPlaceIterable, Iterator};
3 use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, NeverShortCircuit, Residual, Try};
30 #[stable(feature = "rust1", since = "1.0.0")]
32 chain::Chain, cycle::Cycle, enumerate::Enumerate, filter::Filter, filter_map::FilterMap,
33 flatten::FlatMap, fuse::Fuse, inspect::Inspect, map::Map, peekable::Peekable, rev::Rev,
34 scan::Scan, skip::Skip, skip_while::SkipWhile, take::Take, take_while::TakeWhile, zip::Zip,
37 #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
38 pub use self::array_chunks::ArrayChunks;
40 #[unstable(feature = "std_internals", issue = "none")]
41 pub use self::by_ref_sized::ByRefSized;
43 #[stable(feature = "iter_cloned", since = "1.1.0")]
44 pub use self::cloned::Cloned;
46 #[stable(feature = "iterator_step_by", since = "1.28.0")]
47 pub use self::step_by::StepBy;
49 #[stable(feature = "iterator_flatten", since = "1.29.0")]
50 pub use self::flatten::Flatten;
52 #[stable(feature = "iter_copied", since = "1.36.0")]
53 pub use self::copied::Copied;
55 #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
56 pub use self::intersperse::{Intersperse, IntersperseWith};
58 #[stable(feature = "iter_map_while", since = "1.57.0")]
59 pub use self::map_while::MapWhile;
61 #[unstable(feature = "trusted_random_access", issue = "none")]
62 pub use self::zip::TrustedRandomAccess;
64 #[unstable(feature = "trusted_random_access", issue = "none")]
65 pub use self::zip::TrustedRandomAccessNoCoerce;
67 #[stable(feature = "iter_zip", since = "1.59.0")]
68 pub use self::zip::zip;
70 /// This trait provides transitive access to source-stage in an iterator-adapter pipeline
71 /// under the conditions that
72 /// * the iterator source `S` itself implements `SourceIter<Source = S>`
73 /// * there is a delegating implementation of this trait for each adapter in the pipeline between
74 /// the source and the pipeline consumer.
76 /// When the source is an owning iterator struct (commonly called `IntoIter`) then
77 /// this can be useful for specializing [`FromIterator`] implementations or recovering the
78 /// remaining elements after an iterator has been partially exhausted.
80 /// Note that implementations do not necessarily have to provide access to the inner-most
81 /// source of a pipeline. A stateful intermediate adapter might eagerly evaluate a part
82 /// of the pipeline and expose its internal storage as source.
84 /// The trait is unsafe because implementers must uphold additional safety properties.
85 /// See [`as_inner`] for details.
87 /// The primary use of this trait is in-place iteration. Refer to the [`vec::in_place_collect`]
88 /// module documentation for more information.
90 /// [`vec::in_place_collect`]: ../../../../alloc/vec/in_place_collect/index.html
94 /// Retrieving a partially consumed source:
97 /// # #![feature(inplace_iteration)]
98 /// # use std::iter::SourceIter;
100 /// let mut iter = vec![9, 9, 9].into_iter().map(|i| i * i);
101 /// let _ = iter.next();
102 /// let mut remainder = std::mem::replace(unsafe { iter.as_inner() }, Vec::new().into_iter());
103 /// println!("n = {} elements remaining", remainder.len());
106 /// [`FromIterator`]: crate::iter::FromIterator
107 /// [`as_inner`]: SourceIter::as_inner
108 #[unstable(issue = "none", feature = "inplace_iteration")]
110 #[rustc_specialization_trait]
111 pub unsafe trait SourceIter {
112 /// A source stage in an iterator pipeline.
115 /// Retrieve the source of an iterator pipeline.
119 /// Implementations of must return the same mutable reference for their lifetime, unless
120 /// replaced by a caller.
121 /// Callers may only replace the reference when they stopped iteration and drop the
122 /// iterator pipeline after extracting the source.
124 /// This means iterator adapters can rely on the source not changing during
125 /// iteration but they cannot rely on it in their Drop implementations.
127 /// Implementing this method means adapters relinquish private-only access to their
128 /// source and can only rely on guarantees made based on method receiver types.
129 /// The lack of restricted access also requires that adapters must uphold the source's
130 /// public API even when they have access to its internals.
132 /// Callers in turn must expect the source to be in any state that is consistent with
133 /// its public API since adapters sitting between it and the source have the same
134 /// access. In particular an adapter may have consumed more elements than strictly necessary.
136 /// The overall goal of these requirements is to let the consumer of a pipeline use
137 /// * whatever remains in the source after iteration has stopped
138 /// * the memory that has become unused by advancing a consuming iterator
140 /// [`next()`]: Iterator::next()
141 unsafe fn as_inner(&mut self) -> &mut Self::Source;
144 /// An iterator adapter that produces output as long as the underlying
145 /// iterator produces values where `Try::branch` says to `ControlFlow::Continue`.
147 /// If a `ControlFlow::Break` is encountered, the iterator stops and the
148 /// residual is stored.
149 pub(crate) struct GenericShunt<'a, I, R> {
151 residual: &'a mut Option<R>,
154 /// Process the given iterator as if it yielded a the item's `Try::Output`
155 /// type instead. Any `Try::Residual`s encountered will stop the inner iterator
156 /// and be propagated back to the overall result.
157 pub(crate) fn try_process<I, T, R, F, U>(iter: I, mut f: F) -> ChangeOutputType<I::Item, U>
159 I: Iterator<Item: Try<Output = T, Residual = R>>,
160 for<'a> F: FnMut(GenericShunt<'a, I, R>) -> U,
163 let mut residual = None;
164 let shunt = GenericShunt { iter, residual: &mut residual };
165 let value = f(shunt);
167 Some(r) => FromResidual::from_residual(r),
168 None => Try::from_output(value),
172 impl<I, R> Iterator for GenericShunt<'_, I, R>
174 I: Iterator<Item: Try<Residual = R>>,
176 type Item = <I::Item as Try>::Output;
178 fn next(&mut self) -> Option<Self::Item> {
179 self.try_for_each(ControlFlow::Break).break_value()
182 fn size_hint(&self) -> (usize, Option<usize>) {
183 if self.residual.is_some() {
186 let (_, upper) = self.iter.size_hint();
191 fn try_fold<B, F, T>(&mut self, init: B, mut f: F) -> T
193 F: FnMut(B, Self::Item) -> T,
197 .try_fold(init, |acc, x| match Try::branch(x) {
198 ControlFlow::Continue(x) => ControlFlow::from_try(f(acc, x)),
199 ControlFlow::Break(r) => {
200 *self.residual = Some(r);
201 ControlFlow::Break(try { acc })
207 fn fold<B, F>(mut self, init: B, mut fold: F) -> B
210 F: FnMut(B, Self::Item) -> B,
212 self.try_fold(init, ConstFnMutClosure::new(&mut fold, NeverShortCircuit::wrap_mut_2_imp)).0
216 #[unstable(issue = "none", feature = "inplace_iteration")]
217 unsafe impl<I, R> SourceIter for GenericShunt<'_, I, R>
221 type Source = I::Source;
224 unsafe fn as_inner(&mut self) -> &mut Self::Source {
225 // SAFETY: unsafe function forwarding to unsafe function with the same requirements
226 unsafe { SourceIter::as_inner(&mut self.iter) }
230 // SAFETY: GenericShunt::next calls `I::try_for_each`, which has to advance `iter`
231 // in order to return `Some(_)`. Since `iter` has type `I: InPlaceIterable` it's
232 // guaranteed that at least one item will be moved out from the underlying source.
233 #[unstable(issue = "none", feature = "inplace_iteration")]
234 unsafe impl<I, T, R> InPlaceIterable for GenericShunt<'_, I, R> where
235 I: Iterator<Item: Try<Output = T, Residual = R>> + InPlaceIterable