]>
Commit | Line | Data |
---|---|---|
fc512014 XL |
1 | use crate::iter::{InPlaceIterable, Iterator}; |
2 | use crate::ops::{ControlFlow, Try}; | |
9fa01778 XL |
3 | |
4 | mod chain; | |
fc512014 XL |
5 | mod cloned; |
6 | mod copied; | |
7 | mod cycle; | |
8 | mod enumerate; | |
9 | mod filter; | |
10 | mod filter_map; | |
9fa01778 | 11 | mod flatten; |
ba9703b0 | 12 | mod fuse; |
fc512014 | 13 | mod inspect; |
5869c6ff | 14 | mod intersperse; |
fc512014 XL |
15 | mod map; |
16 | mod map_while; | |
17 | mod peekable; | |
18 | mod rev; | |
19 | mod scan; | |
20 | mod skip; | |
21 | mod skip_while; | |
22 | mod step_by; | |
23 | mod take; | |
24 | mod take_while; | |
9fa01778 XL |
25 | mod zip; |
26 | ||
fc512014 XL |
27 | pub 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")] | |
34 | pub use self::cloned::Cloned; | |
35 | ||
36 | #[stable(feature = "iterator_step_by", since = "1.28.0")] | |
37 | pub use self::step_by::StepBy; | |
38 | ||
39 | #[stable(feature = "iterator_flatten", since = "1.29.0")] | |
40 | pub use self::flatten::Flatten; | |
41 | ||
42 | #[stable(feature = "iter_copied", since = "1.36.0")] | |
43 | pub use self::copied::Copied; | |
44 | ||
dc3f5686 | 45 | #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] |
5869c6ff XL |
46 | pub use self::intersperse::{Intersperse, IntersperseWith}; |
47 | ||
fc512014 XL |
48 | #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] |
49 | pub use self::map_while::MapWhile; | |
50 | ||
1b1a35ee XL |
51 | #[unstable(feature = "trusted_random_access", issue = "none")] |
52 | pub use self::zip::TrustedRandomAccess; | |
9fa01778 | 53 | |
94222f64 XL |
54 | #[unstable(feature = "trusted_random_access", issue = "none")] |
55 | pub use self::zip::TrustedRandomAccessNoCoerce; | |
56 | ||
cdc7bbd5 XL |
57 | #[unstable(feature = "iter_zip", issue = "83574")] |
58 | pub 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 |
95 | pub 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. | |
133 | pub(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. | |
141 | pub(crate) fn process_results<I, T, E, F, U>(iter: I, mut f: F) -> Result<U, E> | |
142 | where | |
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 | ||
152 | impl<I, T, E> Iterator for ResultShunt<'_, I, E> | |
dfeec247 XL |
153 | where |
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")] | |
203 | unsafe impl<S: Iterator, I, E> SourceIter for ResultShunt<'_, I, E> | |
204 | where | |
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")] | |
220 | unsafe impl<I, T, E> InPlaceIterable for ResultShunt<'_, I, E> where | |
221 | I: Iterator<Item = Result<T, E>> + InPlaceIterable | |
222 | { | |
223 | } |