Skip to content

Commit 3334802

Browse files
committed
Refactoring use commun code between option, result and accum
1 parent c43753f commit 3334802

File tree

5 files changed

+141
-210
lines changed

5 files changed

+141
-210
lines changed

src/libcore/iter/adapters/mod.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,3 +2062,138 @@ impl<I: ExactSizeIterator, F> ExactSizeIterator for Inspect<I, F>
20622062
#[stable(feature = "fused", since = "1.26.0")]
20632063
impl<I: FusedIterator, F> FusedIterator for Inspect<I, F>
20642064
where F: FnMut(&I::Item) {}
2065+
2066+
/// An iterator adapter that produces output as long as the underlying
2067+
/// iterator produces `Option::Some` values.
2068+
pub(crate) struct OptionShunt<I> {
2069+
iter: I,
2070+
exited_early: bool,
2071+
}
2072+
2073+
impl<I, T> OptionShunt<I>
2074+
where
2075+
I: Iterator<Item = Option<T>>,
2076+
{
2077+
/// Process the given iterator as if it yielded a `T` instead of a
2078+
/// `Option<T>`. Any `None` value will stop the inner iterator and
2079+
/// the overall result will be a `None`.
2080+
pub fn process<F, U>(iter: I, mut f: F) -> Option<U>
2081+
where
2082+
F: FnMut(&mut Self) -> U,
2083+
{
2084+
let mut shunt = OptionShunt::new(iter);
2085+
let value = f(shunt.by_ref());
2086+
shunt.reconstruct(value)
2087+
}
2088+
2089+
fn new(iter: I) -> Self {
2090+
OptionShunt {
2091+
iter,
2092+
exited_early: false,
2093+
}
2094+
}
2095+
2096+
/// Consume the adapter and rebuild a `Option` value.
2097+
fn reconstruct<U>(self, val: U) -> Option<U> {
2098+
if self.exited_early {
2099+
None
2100+
} else {
2101+
Some(val)
2102+
}
2103+
}
2104+
}
2105+
2106+
impl<I, T> Iterator for OptionShunt<I>
2107+
where
2108+
I: Iterator<Item = Option<T>>,
2109+
{
2110+
type Item = T;
2111+
2112+
fn next(&mut self) -> Option<Self::Item> {
2113+
match self.iter.next() {
2114+
Some(Some(v)) => Some(v),
2115+
Some(None) => {
2116+
self.exited_early = true;
2117+
None
2118+
}
2119+
None => None,
2120+
}
2121+
}
2122+
2123+
fn size_hint(&self) -> (usize, Option<usize>) {
2124+
if self.exited_early {
2125+
(0, Some(0))
2126+
} else {
2127+
let (_, upper) = self.iter.size_hint();
2128+
(0, upper)
2129+
}
2130+
}
2131+
}
2132+
2133+
/// An iterator adapter that produces output as long as the underlying
2134+
/// iterator produces `Result::Ok` values.
2135+
///
2136+
/// If an error is encountered, the iterator stops and the error is
2137+
/// stored. The error may be recovered later via `reconstruct`.
2138+
pub(crate) struct ResultShunt<I, E> {
2139+
iter: I,
2140+
error: Option<E>,
2141+
}
2142+
2143+
impl<I, T, E> ResultShunt<I, E>
2144+
where I: Iterator<Item = Result<T, E>>
2145+
{
2146+
/// Process the given iterator as if it yielded a `T` instead of a
2147+
/// `Result<T, _>`. Any errors will stop the inner iterator and
2148+
/// the overall result will be an error.
2149+
pub fn process<F, U>(iter: I, mut f: F) -> Result<U, E>
2150+
where F: FnMut(&mut Self) -> U
2151+
{
2152+
let mut shunt = ResultShunt::new(iter);
2153+
let value = f(shunt.by_ref());
2154+
shunt.reconstruct(value)
2155+
}
2156+
2157+
fn new(iter: I) -> Self {
2158+
ResultShunt {
2159+
iter,
2160+
error: None,
2161+
}
2162+
}
2163+
2164+
/// Consume the adapter and rebuild a `Result` value. This should
2165+
/// *always* be called, otherwise any potential error would be
2166+
/// lost.
2167+
fn reconstruct<U>(self, val: U) -> Result<U, E> {
2168+
match self.error {
2169+
None => Ok(val),
2170+
Some(e) => Err(e),
2171+
}
2172+
}
2173+
}
2174+
2175+
impl<I, T, E> Iterator for ResultShunt<I, E>
2176+
where I: Iterator<Item = Result<T, E>>
2177+
{
2178+
type Item = T;
2179+
2180+
fn next(&mut self) -> Option<Self::Item> {
2181+
match self.iter.next() {
2182+
Some(Ok(v)) => Some(v),
2183+
Some(Err(e)) => {
2184+
self.error = Some(e);
2185+
None
2186+
}
2187+
None => None,
2188+
}
2189+
}
2190+
2191+
fn size_hint(&self) -> (usize, Option<usize>) {
2192+
if self.error.is_some() {
2193+
(0, Some(0))
2194+
} else {
2195+
let (_, upper) = self.iter.size_hint();
2196+
(0, upper)
2197+
}
2198+
}
2199+
}

src/libcore/iter/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ pub use self::adapters::Flatten;
360360
#[stable(feature = "iter_copied", since = "1.36.0")]
361361
pub use self::adapters::Copied;
362362

363-
pub(crate) use self::adapters::TrustedRandomAccess;
363+
pub(crate) use self::adapters::{TrustedRandomAccess, OptionShunt, ResultShunt};
364364

365365
mod range;
366366
mod sources;

src/libcore/iter/traits/accum.rs

Lines changed: 1 addition & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::ops::{Mul, Add};
22
use crate::num::Wrapping;
3+
use crate::iter::adapters::{OptionShunt, ResultShunt};
34

45
/// Trait to represent types that can be created by summing up an iterator.
56
///
@@ -114,74 +115,6 @@ macro_rules! float_sum_product {
114115
integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
115116
float_sum_product! { f32 f64 }
116117

117-
/// An iterator adapter that produces output as long as the underlying
118-
/// iterator produces `Result::Ok` values.
119-
///
120-
/// If an error is encountered, the iterator stops and the error is
121-
/// stored. The error may be recovered later via `reconstruct`.
122-
struct ResultShunt<I, E> {
123-
iter: I,
124-
error: Option<E>,
125-
}
126-
127-
impl<I, T, E> ResultShunt<I, E>
128-
where I: Iterator<Item = Result<T, E>>
129-
{
130-
/// Process the given iterator as if it yielded a `T` instead of a
131-
/// `Result<T, _>`. Any errors will stop the inner iterator and
132-
/// the overall result will be an error.
133-
pub fn process<F, U>(iter: I, mut f: F) -> Result<U, E>
134-
where F: FnMut(&mut Self) -> U
135-
{
136-
let mut shunt = ResultShunt::new(iter);
137-
let value = f(shunt.by_ref());
138-
shunt.reconstruct(value)
139-
}
140-
141-
fn new(iter: I) -> Self {
142-
ResultShunt {
143-
iter,
144-
error: None,
145-
}
146-
}
147-
148-
/// Consume the adapter and rebuild a `Result` value. This should
149-
/// *always* be called, otherwise any potential error would be
150-
/// lost.
151-
fn reconstruct<U>(self, val: U) -> Result<U, E> {
152-
match self.error {
153-
None => Ok(val),
154-
Some(e) => Err(e),
155-
}
156-
}
157-
}
158-
159-
impl<I, T, E> Iterator for ResultShunt<I, E>
160-
where I: Iterator<Item = Result<T, E>>
161-
{
162-
type Item = T;
163-
164-
fn next(&mut self) -> Option<Self::Item> {
165-
match self.iter.next() {
166-
Some(Ok(v)) => Some(v),
167-
Some(Err(e)) => {
168-
self.error = Some(e);
169-
None
170-
}
171-
None => None,
172-
}
173-
}
174-
175-
fn size_hint(&self) -> (usize, Option<usize>) {
176-
if self.error.is_some() {
177-
(0, Some(0))
178-
} else {
179-
let (_, upper) = self.iter.size_hint();
180-
(0, upper)
181-
}
182-
}
183-
}
184-
185118
#[stable(feature = "iter_arith_traits_result", since="1.16.0")]
186119
impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
187120
where T: Sum<U>,
@@ -224,73 +157,6 @@ impl<T, U, E> Product<Result<U, E>> for Result<T, E>
224157
}
225158
}
226159

227-
/// An iterator adapter that produces output as long as the underlying
228-
/// iterator produces `Option::Some` values.
229-
struct OptionShunt<I> {
230-
iter: I,
231-
exited_early: bool,
232-
}
233-
234-
impl<I, T> OptionShunt<I>
235-
where
236-
I: Iterator<Item = Option<T>>,
237-
{
238-
/// Process the given iterator as if it yielded a `T` instead of a
239-
/// `Option<T>`. Any `None` value will stop the inner iterator and
240-
/// the overall result will be a `None`.
241-
pub fn process<F, U>(iter: I, mut f: F) -> Option<U>
242-
where
243-
F: FnMut(&mut Self) -> U,
244-
{
245-
let mut shunt = OptionShunt::new(iter);
246-
let value = f(shunt.by_ref());
247-
shunt.reconstruct(value)
248-
}
249-
250-
fn new(iter: I) -> Self {
251-
OptionShunt {
252-
iter,
253-
exited_early: false,
254-
}
255-
}
256-
257-
/// Consume the adapter and rebuild a `Option` value.
258-
fn reconstruct<U>(self, val: U) -> Option<U> {
259-
if self.exited_early {
260-
None
261-
} else {
262-
Some(val)
263-
}
264-
}
265-
}
266-
267-
impl<I, T> Iterator for OptionShunt<I>
268-
where
269-
I: Iterator<Item = Option<T>>,
270-
{
271-
type Item = T;
272-
273-
fn next(&mut self) -> Option<Self::Item> {
274-
match self.iter.next() {
275-
Some(Some(v)) => Some(v),
276-
Some(None) => {
277-
self.exited_early = true;
278-
None
279-
}
280-
None => None,
281-
}
282-
}
283-
284-
fn size_hint(&self) -> (usize, Option<usize>) {
285-
if self.exited_early {
286-
(0, Some(0))
287-
} else {
288-
let (_, upper) = self.iter.size_hint();
289-
(0, upper)
290-
}
291-
}
292-
}
293-
294160
#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
295161
impl<T, U> Sum<Option<U>> for Option<T>
296162
where

src/libcore/option.rs

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@
135135
136136
#![stable(feature = "rust1", since = "1.0.0")]
137137

138-
use crate::iter::{FromIterator, FusedIterator, TrustedLen};
138+
use crate::iter::{FromIterator, FusedIterator, TrustedLen, OptionShunt};
139139
use crate::{convert, fmt, hint, mem, ops::{self, Deref, DerefMut}};
140140
use crate::pin::Pin;
141141

@@ -1499,45 +1499,7 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
14991499
// FIXME(#11084): This could be replaced with Iterator::scan when this
15001500
// performance bug is closed.
15011501

1502-
struct Adapter<Iter> {
1503-
iter: Iter,
1504-
found_none: bool,
1505-
}
1506-
1507-
impl<T, Iter: Iterator<Item=Option<T>>> Iterator for Adapter<Iter> {
1508-
type Item = T;
1509-
1510-
#[inline]
1511-
fn next(&mut self) -> Option<T> {
1512-
match self.iter.next() {
1513-
Some(Some(value)) => Some(value),
1514-
Some(None) => {
1515-
self.found_none = true;
1516-
None
1517-
}
1518-
None => None,
1519-
}
1520-
}
1521-
1522-
#[inline]
1523-
fn size_hint(&self) -> (usize, Option<usize>) {
1524-
if self.found_none {
1525-
(0, Some(0))
1526-
} else {
1527-
let (_, upper) = self.iter.size_hint();
1528-
(0, upper)
1529-
}
1530-
}
1531-
}
1532-
1533-
let mut adapter = Adapter { iter: iter.into_iter(), found_none: false };
1534-
let v: V = FromIterator::from_iter(adapter.by_ref());
1535-
1536-
if adapter.found_none {
1537-
None
1538-
} else {
1539-
Some(v)
1540-
}
1502+
OptionShunt::process(iter.into_iter(), |i| i.collect())
15411503
}
15421504
}
15431505

0 commit comments

Comments
 (0)