From 44148cac50646d4a26c4a58c1c3719ee92b71496 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Tue, 11 Sep 2018 07:37:50 -0700 Subject: [PATCH 01/34] Implement Clone for iterator adaptors. An iterator implementing clone lets it serve, not just as a pointer into the sequence of items it will produce, but as a reusable representation of that sequence. --- src/lib.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9f2ef07..b7bf640 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -856,7 +856,7 @@ impl IntoFallibleIterator for I /// An iterator which applies a fallible transform to the elements of the /// underlying iterator. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct AndThen { it: T, f: F, @@ -884,7 +884,7 @@ impl FallibleIterator for AndThen } } -#[derive(Debug)] +#[derive(Clone, Debug)] enum ChainState { Both, Front, @@ -892,7 +892,7 @@ enum ChainState { } /// An iterator which yields the elements of one iterator followed by another. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Chain { front: T, back: U, @@ -970,7 +970,7 @@ impl DoubleEndedFallibleIterator for Chain } /// An iterator which clones the elements of the underlying iterator. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Cloned(I); impl<'a, T, I> FallibleIterator for Cloned @@ -1015,7 +1015,7 @@ pub fn convert(it: I) -> Convert } /// A fallible iterator that wraps a normal iterator over `Result`s. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Convert(I); impl FallibleIterator for Convert @@ -1054,7 +1054,7 @@ impl DoubleEndedFallibleIterator for Convert /// An iterator that yields the iteration count as well as the values of the /// underlying iterator. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Enumerate { it: I, n: usize, @@ -1092,7 +1092,7 @@ impl FallibleIterator for Enumerate /// An iterator which uses a predicate to determine which values of the /// underlying iterator should be yielded. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Filter { it: I, f: F, @@ -1140,7 +1140,7 @@ impl DoubleEndedFallibleIterator for Filter /// An iterator which both filters and maps the values of the underlying /// iterator. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct FilterMap { it: I, f: F, @@ -1188,7 +1188,7 @@ impl DoubleEndedFallibleIterator for FilterMap /// An iterator that yields `Ok(None)` forever after the underlying iterator /// yields `Ok(None)` once. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Fuse { it: I, done: bool, @@ -1232,7 +1232,7 @@ impl FallibleIterator for Fuse } /// A normal (non-fallible) iterator which wraps a fallible iterator. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Iterator(I); impl iter::Iterator for Iterator @@ -1270,7 +1270,7 @@ impl DoubleEndedIterator for Iterator /// An iterator which applies a transform to the elements of the underlying /// iterator. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Map { it: I, f: F, @@ -1311,7 +1311,7 @@ impl DoubleEndedFallibleIterator for Map /// An iterator which applies a transform to the errors of the underlying /// iterator. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct MapErr { it: I, f: F, @@ -1351,7 +1351,7 @@ impl DoubleEndedFallibleIterator for MapErr } /// An iterator which can look at the next element without consuming it. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Peekable { it: I, next: Option, @@ -1399,7 +1399,7 @@ impl FallibleIterator for Peekable /// An iterator which yields elements of the underlying iterator in reverse /// order. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Rev(I); impl FallibleIterator for Rev @@ -1435,7 +1435,7 @@ impl DoubleEndedFallibleIterator for Rev /// An iterator which yields a limited number of elements from the underlying /// iterator. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Take { it: I, remaining: usize, @@ -1469,7 +1469,7 @@ impl FallibleIterator for Take /// An iterator that yields pairs of this iterator's and another iterator's /// values. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Zip(T, U); impl FallibleIterator for Zip From a38405bb72d67d454e2f112a176252635545bac5 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Tue, 11 Sep 2018 13:09:03 -0700 Subject: [PATCH 02/34] Doc fix: Point out analogy between `and_then` and `map`. --- src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 9f2ef07..ffdb96c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -132,6 +132,10 @@ pub trait FallibleIterator { /// Returns an iterator which applies a fallible transform to the elements /// of the underlying iterator. + /// + /// This is very much like the [`map`](#method.map) method, differing only + /// in the transforming closure's return type: `Result` instead of + /// just `B`. #[inline] fn and_then(self, f: F) -> AndThen where Self: Sized, @@ -306,8 +310,11 @@ pub trait FallibleIterator { Ok(last) } - /// Returns an iterator which applies a transform to the elements of the + /// Returns an iterator which applies a transform `f` to the elements of the /// underlying iterator. + /// + /// If your transform closure needs to be fallible, consider using the + /// [`and_then`](#method.and_then) method instead. #[inline] fn map(self, f: F) -> Map where F: FnMut(Self::Item) -> B, From 6b4688563ac0c5b198bb3f373252ec99f577802a Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Tue, 11 Sep 2018 19:29:03 -0700 Subject: [PATCH 03/34] Update CircleCI 'stable' toolchain to 1.26.0. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 97ed188..1834f91 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,7 +22,7 @@ version: 2 jobs: stable: docker: - - image: rust:1.19.0 + - image: rust:1.26.0 environment: RUSTFLAGS: -D warnings working_directory: ~/build From 8cfd33fb2979b31f242d0fd945bf3041b10623af Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Tue, 11 Sep 2018 13:25:03 -0700 Subject: [PATCH 04/34] Add tests for double-ended iterator behavior. The crate provides the following implementations of DoubleEndedFallibleIterator: - Chain: double-ended behavior already tested - Convert: used throughout existing tests - Cloned: untested but trivial - Filter: added new tests - FilterMap: added new tests - Iterator: added new tests - Map: added new tests - MapErr: added new tests --- src/test.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/test.rs b/src/test.rs index 40c7ba5..f3a73b7 100644 --- a/src/test.rs +++ b/src/test.rs @@ -66,7 +66,8 @@ fn enumerate() { fn filter() { let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)).filter(|&x| x % 2 == 0); - assert_eq!(it.collect::>().unwrap(), [0, 2]); + assert_eq!(it.clone().collect::>().unwrap(), [0, 2]); + assert_eq!(it.rev().collect::>().unwrap(), [2, 0]); } #[test] @@ -74,13 +75,14 @@ fn filter_map() { let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)) .filter_map(|x| { if x % 2 == 0 { - Some(x + 1) + Some(x + 10) } else { None } }); - assert_eq!(it.collect::>().unwrap(), [1, 3]); + assert_eq!(it.clone().collect::>().unwrap(), [10, 12]); + assert_eq!(it.rev().collect::>().unwrap(), [12, 10]); } #[test] @@ -97,12 +99,51 @@ fn fold() { assert_eq!(it.fold(0, |a, b| a + b).unwrap(), 6); } +#[test] +fn iterator() { + let it = convert("ab cd".chars().map(|c| { + if c.is_whitespace() { + Err(()) + } else { + Ok(c) + } + })); + + assert!(it.clone().count().is_err()); + assert!(it.clone().rev().count().is_err()); + assert_eq!(it.clone().iterator().count(), 5); + assert_eq!(it.clone().iterator().rev().count(), 5); +} + #[test] fn last() { let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); assert_eq!(it.last().unwrap(), Some(3)); } +#[test] +fn map() { + let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); + let it = it.map(|n| 10-n); + + assert_eq!(it.clone().collect::>(), Ok(vec![10, 9, 8, 7])); + assert_eq!(it.rev().collect::>(), Ok(vec![7, 8, 9, 10])); +} + +#[test] +fn map_err() { + let it = convert(vec![0, 1, 2, 3].into_iter().map(|n| { + if n % 2 == 0 { + Ok(n) + } else { + Err(n) + } + })); + + assert_eq!(it.clone().collect::>(), Err(1)); + assert_eq!(it.rev().collect::>(), Err(3)); +} + #[test] fn max() { let it = convert(vec![0, 3, 1, -10].into_iter().map(Ok::)); From d1fbce48bfa124f54d0878e99d0ba8902f82ef59 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Tue, 11 Sep 2018 14:40:46 -0700 Subject: [PATCH 05/34] Let closures passed to `FallibleIterator` methods be fallible. This changes the signatures of the closures accepted by the following methods: - all - any - filter - filter_map - find - fold - max_by_key - min_by_key - position Each one is changes to return a `Result` instead of a plain `T`, and thus can report errors that are propagated to the caller - or to the consumer, in the case of adapter methods. --- Cargo.toml | 2 +- src/lib.rs | 166 +++++++++++++++++++++------------------------------- src/test.rs | 151 +++++++++++++++++++++++++++++++---------------- 3 files changed, 169 insertions(+), 150 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 81ab028..0deccfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fallible-iterator" -version = "0.1.5" +version = "0.2.0" authors = ["Steven Fackler "] license = "MIT/Apache-2.0" description = "Fallible iterator traits" diff --git a/src/lib.rs b/src/lib.rs index 979fc82..c1d256c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,27 @@ //! // work with item //! } //! ``` +//! +//! ## Fallible closure arguments +//! +//! Like `Iterator`, many `FallibleIterator` methods take closures as arguments. +//! These use the same signatures as their `Iterator` counterparts, except that +//! `FallibleIterator` expects the closures to be fallible: they return +//! `Result` instead of simply `T`. +//! +//! For example, the standard library's `Iterator::filter` adapter method +//! filters the underlying iterator according to a predicate provided by the +//! user, whose return type is `bool`. In `FallibleIterator::filter`, however, +//! the predicate returns `Result`: +//! +//! ``` +//! # use std::error::Error; +//! # use std::str::FromStr; +//! # use fallible_iterator::{convert, FallibleIterator}; +//! let numbers = convert("100\n200\nfern\n400".lines().map(Ok::<&str, Box>)); +//! let big_numbers = numbers.filter(|n| Ok(u64::from_str(n)? > 100)); +//! assert!(big_numbers.count().is_err()); +//! ``` #![doc(html_root_url = "https://docs.rs/fallible-iterator/0.1")] #![warn(missing_docs)] #![cfg_attr(feature = "alloc", feature(alloc))] @@ -116,13 +137,14 @@ pub trait FallibleIterator { } /// Determines if all elements of this iterator match a predicate. + /// The predicate may fail; such failures are passed to the caller. #[inline] fn all(&mut self, mut f: F) -> Result where Self: Sized, - F: FnMut(Self::Item) -> bool + F: FnMut(Self::Item) -> Result { while let Some(v) = try!(self.next()) { - if !f(v) { + if !f(v)? { return Ok(false); } } @@ -130,28 +152,15 @@ pub trait FallibleIterator { Ok(true) } - /// Returns an iterator which applies a fallible transform to the elements - /// of the underlying iterator. - /// - /// This is very much like the [`map`](#method.map) method, differing only - /// in the transforming closure's return type: `Result` instead of - /// just `B`. - #[inline] - fn and_then(self, f: F) -> AndThen - where Self: Sized, - F: FnMut(Self::Item) -> Result - { - AndThen { it: self, f: f } - } - /// Determines if any element of this iterator matches a predicate. + /// The predicate may fail; such failures are passed to the caller. #[inline] fn any(&mut self, mut f: F) -> Result where Self: Sized, - F: FnMut(Self::Item) -> bool + F: FnMut(Self::Item) -> Result { while let Some(v) = try!(self.next()) { - if f(v) { + if f(v)? { return Ok(true); } } @@ -227,32 +236,35 @@ pub trait FallibleIterator { } /// Returns an iterator which uses a predicate to determine which values - /// should be yielded. + /// should be yielded. The predicate may fail; such failures are passed to + /// the caller. #[inline] fn filter(self, f: F) -> Filter where Self: Sized, - F: FnMut(&Self::Item) -> bool + F: FnMut(&Self::Item) -> Result { Filter { it: self, f: f } } - /// Returns an iterator which both filters and maps. + /// Returns an iterator which both filters and maps. The closure may fail; + /// such failures are passed along to the consumer. #[inline] fn filter_map(self, f: F) -> FilterMap where Self: Sized, - F: FnMut(Self::Item) -> Option + F: FnMut(Self::Item) -> Result, Self::Error> { FilterMap { it: self, f: f } } /// Returns the first element of the iterator that matches a predicate. + /// The predicate may fail; such failures are passed along to the caller. #[inline] fn find(&mut self, mut f: F) -> Result, Self::Error> where Self: Sized, - F: FnMut(&Self::Item) -> bool + F: FnMut(&Self::Item) -> Result { while let Some(v) = try!(self.next()) { - if f(&v) { + if f(&v)? { return Ok(Some(v)); } } @@ -277,14 +289,15 @@ pub trait FallibleIterator { } /// Applies a function over the elements of the iterator, producing a single - /// final value. + /// final value. The function may fail; such failures are returned to the + /// caller. #[inline] fn fold(mut self, mut init: B, mut f: F) -> Result where Self: Sized, - F: FnMut(B, Self::Item) -> B + F: FnMut(B, Self::Item) -> Result { while let Some(v) = try!(self.next()) { - init = f(init, v); + init = f(init, v)?; } Ok(init) @@ -310,15 +323,12 @@ pub trait FallibleIterator { Ok(last) } - /// Returns an iterator which applies a transform `f` to the elements of the - /// underlying iterator. - /// - /// If your transform closure needs to be fallible, consider using the - /// [`and_then`](#method.and_then) method instead. + /// Returns an iterator which applies a fallible transform to the elements + /// of the underlying iterator. #[inline] - fn map(self, f: F) -> Map - where F: FnMut(Self::Item) -> B, - Self: Sized + fn map(self, f: F) -> Map + where Self: Sized, + F: FnMut(Self::Item) -> Result { Map { it: self, f: f } } @@ -354,20 +364,20 @@ pub trait FallibleIterator { } /// Returns the element of the iterator which gives the maximum value from - /// the function. + /// the function. The function may fail; such failures are returned to the caller. #[inline] fn max_by_key(mut self, mut f: F) -> Result, Self::Error> where Self: Sized, B: Ord, - F: FnMut(&Self::Item) -> B + F: FnMut(&Self::Item) -> Result { let mut max = match try!(self.next()) { - Some(v) => (f(&v), v), + Some(v) => (f(&v)?, v), None => return Ok(None), }; while let Some(v) = try!(self.next()) { - let b = f(&v); + let b = f(&v)?; if max.0 < b { max = (b, v); } @@ -397,20 +407,20 @@ pub trait FallibleIterator { } /// Returns the element of the iterator which gives the minimum value from - /// the function. + /// the function. The function may fail; such failures are returned to the caller. #[inline] fn min_by_key(mut self, mut f: F) -> Result, Self::Error> where Self: Sized, B: Ord, - F: FnMut(&Self::Item) -> B + F: FnMut(&Self::Item) -> Result { let mut min = match try!(self.next()) { - Some(v) => (f(&v), v), + Some(v) => (f(&v)?, v), None => return Ok(None), }; while let Some(v) = try!(self.next()) { - let b = f(&v); + let b = f(&v)?; if min.0 > b { min = (b, v); } @@ -444,15 +454,16 @@ pub trait FallibleIterator { } /// Returns the position of the first element of this iterator that matches - /// a predicate. + /// a predicate. The predicate may fail; such failures are returned to the + /// caller. #[inline] fn position(&mut self, mut f: F) -> Result, Self::Error> where Self: Sized, - F: FnMut(Self::Item) -> bool + F: FnMut(Self::Item) -> Result { let mut i = 0; while let Some(v) = try!(self.next()) { - if f(v) { + if f(v)? { return Ok(Some(i)); } i += 1; @@ -864,12 +875,12 @@ impl IntoFallibleIterator for I /// An iterator which applies a fallible transform to the elements of the /// underlying iterator. #[derive(Clone, Debug)] -pub struct AndThen { +pub struct Map { it: T, f: F, } -impl FallibleIterator for AndThen +impl FallibleIterator for Map where T: FallibleIterator, F: FnMut(T::Item) -> Result { @@ -1097,7 +1108,7 @@ impl FallibleIterator for Enumerate } } -/// An iterator which uses a predicate to determine which values of the +/// An iterator which uses a fallible predicate to determine which values of the /// underlying iterator should be yielded. #[derive(Clone, Debug)] pub struct Filter { @@ -1107,7 +1118,7 @@ pub struct Filter { impl FallibleIterator for Filter where I: FallibleIterator, - F: FnMut(&I::Item) -> bool + F: FnMut(&I::Item) -> Result { type Item = I::Item; type Error = I::Error; @@ -1115,7 +1126,7 @@ impl FallibleIterator for Filter #[inline] fn next(&mut self) -> Result, I::Error> { while let Some(v) = try!(self.it.next()) { - if (self.f)(&v) { + if (self.f)(&v)? { return Ok(Some(v)); } } @@ -1131,12 +1142,12 @@ impl FallibleIterator for Filter impl DoubleEndedFallibleIterator for Filter where I: DoubleEndedFallibleIterator, - F: FnMut(&I::Item) -> bool + F: FnMut(&I::Item) -> Result { #[inline] fn next_back(&mut self) -> Result, I::Error> { while let Some(v) = try!(self.it.next_back()) { - if (self.f)(&v) { + if (self.f)(&v)? { return Ok(Some(v)); } } @@ -1155,7 +1166,7 @@ pub struct FilterMap { impl FallibleIterator for FilterMap where I: FallibleIterator, - F: FnMut(I::Item) -> Option + F: FnMut(I::Item) -> Result, I::Error> { type Item = B; type Error = I::Error; @@ -1163,7 +1174,7 @@ impl FallibleIterator for FilterMap #[inline] fn next(&mut self) -> Result, I::Error> { while let Some(v) = try!(self.it.next()) { - if let Some(v) = (self.f)(v) { + if let Some(v) = (self.f)(v)? { return Ok(Some(v)); } } @@ -1179,12 +1190,12 @@ impl FallibleIterator for FilterMap impl DoubleEndedFallibleIterator for FilterMap where I: DoubleEndedFallibleIterator, - F: FnMut(I::Item) -> Option + F: FnMut(I::Item) -> Result, I::Error> { #[inline] fn next_back(&mut self) -> Result, I::Error> { while let Some(v) = try!(self.it.next_back()) { - if let Some(v) = (self.f)(v) { + if let Some(v) = (self.f)(v)? { return Ok(Some(v)); } } @@ -1275,47 +1286,6 @@ impl DoubleEndedIterator for Iterator } } -/// An iterator which applies a transform to the elements of the underlying -/// iterator. -#[derive(Clone, Debug)] -pub struct Map { - it: I, - f: F, -} - -impl FallibleIterator for Map - where I: FallibleIterator, - F: FnMut(I::Item) -> B -{ - type Item = B; - type Error = I::Error; - - #[inline] - fn next(&mut self) -> Result, I::Error> { - self.it.next().map(|o| o.map(&mut self.f)) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.it.size_hint() - } - - #[inline] - fn count(self) -> Result { - self.it.count() - } -} - -impl DoubleEndedFallibleIterator for Map - where I: DoubleEndedFallibleIterator, - F: FnMut(I::Item) -> B -{ - #[inline] - fn next_back(&mut self) -> Result, I::Error> { - self.it.next_back().map(|o| o.map(&mut self.f)) - } -} - /// An iterator which applies a transform to the errors of the underlying /// iterator. #[derive(Clone, Debug)] diff --git a/src/test.rs b/src/test.rs index f3a73b7..1ba35a1 100644 --- a/src/test.rs +++ b/src/test.rs @@ -4,32 +4,16 @@ use super::{convert, FallibleIterator, Vec}; #[test] fn all() { - assert!(convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)).all(|&i| i < 4).unwrap()); - assert!(!convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)).all(|&i| i < 4).unwrap()); -} - -#[test] -fn and_then() { - let it = convert(vec![0, 1, 2, 3, 4].into_iter().map(Ok::)).and_then(|n| Ok(n * 2)); - assert_eq!(it.collect::>().unwrap(), [0, 2, 4, 6, 8]); - - let mut it = convert(vec![0, 1, 2, 3, 4].into_iter().map(Ok::)) - .and_then(|n| { - if n == 2 { - Err(()) - } else { - Ok(n * 2) - } - }); - assert_eq!(it.next().unwrap().unwrap(), 0); - assert_eq!(it.next().unwrap().unwrap(), 2); - assert_eq!(it.next(), Err(())); + assert!(convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)).all(|&i| Ok(i < 4)).unwrap()); + assert!(!convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)).all(|&i| Ok(i < 4)).unwrap()); + assert!(convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)).all(|_| Err(())).is_err()); } #[test] fn any() { - assert!(convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)).any(|&i| i == 3).unwrap()); - assert!(!convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)).any(|&i| i == 3).unwrap()); + assert!(convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)).any(|&i| Ok(i == 3)).unwrap()); + assert!(!convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)).any(|&i| Ok(i == 3)).unwrap()); + assert!(convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)).any(|_| Err(())).is_err()); } #[test] @@ -64,39 +48,85 @@ fn enumerate() { #[test] fn filter() { - let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)).filter(|&x| x % 2 == 0); + let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); + let it = it.filter(|&x| { + if x % 2 == 0 { + Ok(x % 3 == 0) + } else { + Err(x) + } + }); - assert_eq!(it.clone().collect::>().unwrap(), [0, 2]); - assert_eq!(it.rev().collect::>().unwrap(), [2, 0]); + assert_eq!(it.clone().collect::>(), Err(1)); + assert_eq!(it.rev().collect::>(), Err(3)); + + let it = convert(vec![0, 2, 4, 6].into_iter().map(Ok::)); + let it = it.filter(|&x| { + if x % 2 == 0 { + Ok(x % 3 == 0) + } else { + Err(x) + } + }); + + assert_eq!(it.clone().collect::>(), Ok(vec![0, 6])); + assert_eq!(it.rev().collect::>(), Ok(vec![6, 0])) } #[test] fn filter_map() { - let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)) - .filter_map(|x| { - if x % 2 == 0 { - Some(x + 10) - } else { - None - } - }); + fn twos_and_threes(x: u32) -> Result, u32> { + if x % 2 == 0 { + Ok(Some(x + 10)) + } else if x % 3 == 0 { + Ok(None) + } else { + Err(x) + } + } + + let it = convert(vec![0, 1, 2, 3, 4, 5, 6].into_iter().map(Ok::)) + .filter_map(twos_and_threes); + + assert_eq!(it.clone().collect::>(), Err(1)); + assert_eq!(it.rev().collect::>(), Err(5)); - assert_eq!(it.clone().collect::>().unwrap(), [10, 12]); - assert_eq!(it.rev().collect::>().unwrap(), [12, 10]); + let it = convert(vec![0, 2, 3, 4, 6].into_iter().map(Ok::)) + .filter_map(twos_and_threes); + + assert_eq!(it.clone().collect::>(), Ok(vec![10, 12, 14, 16])); + assert_eq!(it.rev().collect::>(), Ok(vec![16, 14, 12, 10])); } #[test] fn find() { - let mut it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); + let mut it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); + + assert_eq!(it.find(|x| Ok(x % 2 == 1)), Ok(Some(1))); + assert_eq!(it.next(), Ok(Some(2))); - assert_eq!(it.find(|x| x % 2 == 1).unwrap(), Some(1)); - assert_eq!(it.next().unwrap(), Some(2)); + let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); + assert_eq!(it.clone().find(|&x| if x == 2 { Err(29) } else { Ok(false) }), Err(29)); + assert_eq!(it.clone().find(|&x| if x == 2 { Err(29) } else { Ok(true) }), Ok(Some(0))); + assert_eq!(it.clone().rev().find(|&x| if x == 2 { Err(29) } else { Ok(false) }), Err(29)); + assert_eq!(it.rev().find(|&x| if x == 2 { Err(29) } else { Ok(true) }), Ok(Some(3))); } #[test] fn fold() { - let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); - assert_eq!(it.fold(0, |a, b| a + b).unwrap(), 6); + fn add_smol(a: u32, b: u32) -> Result { + if b <= 2 { + Ok(a + b) + } else { + Err(b) + } + } + + let it = convert(vec![0, 1, 3, 2].into_iter().map(Ok::)); + assert_eq!(it.fold(0, add_smol), Err(3)); + + let it = convert(vec![0, 1, 2, 1].into_iter().map(Ok::)); + assert_eq!(it.fold(0, add_smol), Ok(4)); } #[test] @@ -123,11 +153,20 @@ fn last() { #[test] fn map() { - let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); - let it = it.map(|n| 10-n); + let it = convert(vec![0, 1, 2, 3, 4].into_iter().map(Ok::)).map(|n| Ok(n * 2)); + assert_eq!(it.clone().collect::>().unwrap(), [0, 2, 4, 6, 8]); - assert_eq!(it.clone().collect::>(), Ok(vec![10, 9, 8, 7])); - assert_eq!(it.rev().collect::>(), Ok(vec![7, 8, 9, 10])); + let mut it = convert(vec![0, 1, 2, 3, 4].into_iter().map(Ok::)) + .map(|n| { + if n == 2 { + Err(()) + } else { + Ok(n * 2) + } + }); + assert_eq!(it.next().unwrap().unwrap(), 0); + assert_eq!(it.next().unwrap().unwrap(), 2); + assert_eq!(it.next(), Err(())); } #[test] @@ -152,8 +191,11 @@ fn max() { #[test] fn max_by_key() { - let it = convert(vec![0, 3, 1, -10].into_iter().map(Ok::)); - assert_eq!(it.max_by_key(|&i| -i).unwrap(), Some(-10)); + let it = convert(vec![0, 3, 1, -10].into_iter().map(Ok::)); + assert_eq!(it.clone().max_by_key(|&i| Ok(-i)), Ok(Some(-10))); + // Exercise failure both on the first item, and later. + assert_eq!(it.clone().max_by_key(|&i| Err::(i)), Err(0)); + assert_eq!(it.clone().max_by_key(|&i| if i > 0 { Err(i) } else { Ok(-i) }), Err(3)); } #[test] @@ -164,8 +206,11 @@ fn min() { #[test] fn min_by_key() { - let it = convert(vec![0, 3, 1, -10].into_iter().map(Ok::)); - assert_eq!(it.min_by_key(|&i| -i).unwrap(), Some(3)); + let it = convert(vec![0, 3, 1, -10].into_iter().map(Ok::)); + assert_eq!(it.clone().min_by_key(|&i| Ok(-i)), Ok(Some(3))); + // Exercise failure both on the first item, and later. + assert_eq!(it.clone().min_by_key(|&i| Err::(i)), Err(0)); + assert_eq!(it.clone().min_by_key(|&i| if i > 0 { Err(i) } else { Ok(-i) }), Err(3)); } #[test] @@ -190,9 +235,13 @@ fn peekable() { #[test] fn position() { let mut it = convert(vec![1, 2, 3, 4].into_iter().map(Ok::)); - assert_eq!(it.position(|n| n == 2).unwrap(), Some(1)); - assert_eq!(it.position(|n| n == 3).unwrap(), Some(0)); - assert_eq!(it.position(|n| n == 5).unwrap(), None); + assert_eq!(it.position(|n| Ok(n == 2)).unwrap(), Some(1)); + assert_eq!(it.position(|n| Ok(n == 3)).unwrap(), Some(0)); + assert_eq!(it.position(|n| Ok(n == 5)).unwrap(), None); + + let it = convert(vec![1, 2, 3, 4].into_iter().map(Ok::)); + assert_eq!(it.clone().position(|n| if n == 3 { Err(42) } else { Ok(n == 2) }), Ok(Some(1))); + assert_eq!(it.clone().position(|n| if n == 3 { Err(42) } else { Ok(n == 4) }), Err(42)); } #[test] From 3454d1d1f69f25701d3976c0f26cdcacebcb43b7 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Wed, 12 Sep 2018 23:35:11 -0700 Subject: [PATCH 06/34] =?UTF-8?q?Implement=20DoubleEndedFallibleIterator?= =?UTF-8?q?=20for=20Map=20(n=C3=A9e=20AndThen).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When I used `AndThen` (carrying a fallible closure) to replace the old `Map` (carrying an infallible closure), I didn't notice that `AndThen` didn't have a `DoubleEndedFallibleIterator` implementation, so the replacement effectively deleted `Map`'s implementation. Rebasing on top of the changes from #12 made the omission evident. --- src/lib.rs | 14 ++++++++++++++ src/test.rs | 20 ++++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c1d256c..a3601a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -902,6 +902,20 @@ impl FallibleIterator for Map } } +impl DoubleEndedFallibleIterator for Map + where I: DoubleEndedFallibleIterator, + F: FnMut(I::Item) -> Result +{ + #[inline] + fn next_back(&mut self) -> Result, I::Error> { + match self.it.next_back() { + Ok(Some(v)) => Ok(Some(try!((self.f)(v)))), + Ok(None) => Ok(None), + Err(e) => Err(e), + } + } +} + #[derive(Clone, Debug)] enum ChainState { Both, diff --git a/src/test.rs b/src/test.rs index 1ba35a1..d8f5df0 100644 --- a/src/test.rs +++ b/src/test.rs @@ -155,8 +155,9 @@ fn last() { fn map() { let it = convert(vec![0, 1, 2, 3, 4].into_iter().map(Ok::)).map(|n| Ok(n * 2)); assert_eq!(it.clone().collect::>().unwrap(), [0, 2, 4, 6, 8]); + assert_eq!(it.rev().collect::>().unwrap(), [8, 6, 4, 2, 0]); - let mut it = convert(vec![0, 1, 2, 3, 4].into_iter().map(Ok::)) + let it = convert(vec![0, 1, 2, 3, 4].into_iter().map(Ok::)) .map(|n| { if n == 2 { Err(()) @@ -164,9 +165,20 @@ fn map() { Ok(n * 2) } }); - assert_eq!(it.next().unwrap().unwrap(), 0); - assert_eq!(it.next().unwrap().unwrap(), 2); - assert_eq!(it.next(), Err(())); + + { + let mut it = it.clone(); + assert_eq!(it.next(), Ok(Some(0))); + assert_eq!(it.next(), Ok(Some(2))); + assert_eq!(it.next(), Err(())); + } + + { + let mut it = it.rev(); + assert_eq!(it.next(), Ok(Some(8))); + assert_eq!(it.next(), Ok(Some(6))); + assert_eq!(it.next(), Err(())); + } } #[test] From 85da2b8c5ded0ad4e9d00c4ed8678798c45fe41a Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 19 Sep 2018 20:48:26 -0700 Subject: [PATCH 07/34] rustfmt --- src/lib.rs | 433 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 244 insertions(+), 189 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a3601a7..610ec79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,9 +78,9 @@ extern crate alloc; #[cfg(all(feature = "alloc", not(feature = "std")))] mod imports { pub use alloc::boxed::Box; - pub use alloc::vec::Vec; pub use alloc::collections::btree_map::BTreeMap; pub use alloc::collections::btree_set::BTreeSet; + pub use alloc::vec::Vec; } #[cfg(feature = "std")] @@ -89,9 +89,9 @@ extern crate std; #[cfg(feature = "std")] mod imports { - pub use std::prelude::v1::*; pub use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; pub use std::hash::Hash; + pub use std::prelude::v1::*; } #[cfg(any(feature = "std", feature = "alloc"))] @@ -140,8 +140,9 @@ pub trait FallibleIterator { /// The predicate may fail; such failures are passed to the caller. #[inline] fn all(&mut self, mut f: F) -> Result - where Self: Sized, - F: FnMut(Self::Item) -> Result + where + Self: Sized, + F: FnMut(Self::Item) -> Result, { while let Some(v) = try!(self.next()) { if !f(v)? { @@ -156,8 +157,9 @@ pub trait FallibleIterator { /// The predicate may fail; such failures are passed to the caller. #[inline] fn any(&mut self, mut f: F) -> Result - where Self: Sized, - F: FnMut(Self::Item) -> Result + where + Self: Sized, + F: FnMut(Self::Item) -> Result, { while let Some(v) = try!(self.next()) { if f(v)? { @@ -174,7 +176,8 @@ pub trait FallibleIterator { /// otherwise consume the value. #[inline] fn by_ref(&mut self) -> &mut Self - where Self: Sized + where + Self: Sized, { self } @@ -183,8 +186,9 @@ pub trait FallibleIterator { /// by another. #[inline] fn chain(self, it: I) -> Chain - where I: IntoFallibleIterator, - Self: Sized + where + I: IntoFallibleIterator, + Self: Sized, { Chain { front: self, @@ -196,8 +200,9 @@ pub trait FallibleIterator { /// Returns an iterator which clones all of its elements. #[inline] fn cloned<'a, T>(self) -> Cloned - where Self: Sized + FallibleIterator, - T: 'a + Clone + where + Self: Sized + FallibleIterator, + T: 'a + Clone, { Cloned(self) } @@ -205,7 +210,8 @@ pub trait FallibleIterator { /// Consumes the iterator, returning the number of remaining items. #[inline] fn count(mut self) -> Result - where Self: Sized + where + Self: Sized, { let mut count = 0; while let Some(_) = try!(self.next()) { @@ -220,8 +226,9 @@ pub trait FallibleIterator { /// An `Err` will be returned if any invocation of `next` returns `Err`. #[inline] fn collect(self) -> Result - where T: FromFallibleIterator, - Self: Sized + where + T: FromFallibleIterator, + Self: Sized, { T::from_fallible_iterator(self) } @@ -230,7 +237,8 @@ pub trait FallibleIterator { /// as the value. #[inline] fn enumerate(self) -> Enumerate - where Self: Sized + where + Self: Sized, { Enumerate { it: self, n: 0 } } @@ -240,8 +248,9 @@ pub trait FallibleIterator { /// the caller. #[inline] fn filter(self, f: F) -> Filter - where Self: Sized, - F: FnMut(&Self::Item) -> Result + where + Self: Sized, + F: FnMut(&Self::Item) -> Result, { Filter { it: self, f: f } } @@ -250,8 +259,9 @@ pub trait FallibleIterator { /// such failures are passed along to the consumer. #[inline] fn filter_map(self, f: F) -> FilterMap - where Self: Sized, - F: FnMut(Self::Item) -> Result, Self::Error> + where + Self: Sized, + F: FnMut(Self::Item) -> Result, Self::Error>, { FilterMap { it: self, f: f } } @@ -260,8 +270,9 @@ pub trait FallibleIterator { /// The predicate may fail; such failures are passed along to the caller. #[inline] fn find(&mut self, mut f: F) -> Result, Self::Error> - where Self: Sized, - F: FnMut(&Self::Item) -> Result + where + Self: Sized, + F: FnMut(&Self::Item) -> Result, { while let Some(v) = try!(self.next()) { if f(&v)? { @@ -280,7 +291,8 @@ pub trait FallibleIterator { /// guarantees that `Ok(None)` will always be returned. #[inline] fn fuse(self) -> Fuse - where Self: Sized + where + Self: Sized, { Fuse { it: self, @@ -293,8 +305,9 @@ pub trait FallibleIterator { /// caller. #[inline] fn fold(mut self, mut init: B, mut f: F) -> Result - where Self: Sized, - F: FnMut(B, Self::Item) -> Result + where + Self: Sized, + F: FnMut(B, Self::Item) -> Result, { while let Some(v) = try!(self.next()) { init = f(init, v)?; @@ -306,7 +319,8 @@ pub trait FallibleIterator { /// Returns a normal (non-fallible) iterator over `Result`. #[inline] fn iterator(self) -> Iterator - where Self: Sized + where + Self: Sized, { Iterator(self) } @@ -314,7 +328,8 @@ pub trait FallibleIterator { /// Returns the last element of the iterator. #[inline] fn last(mut self) -> Result, Self::Error> - where Self: Sized + where + Self: Sized, { let mut last = None; while let Some(e) = try!(self.next()) { @@ -327,8 +342,9 @@ pub trait FallibleIterator { /// of the underlying iterator. #[inline] fn map(self, f: F) -> Map - where Self: Sized, - F: FnMut(Self::Item) -> Result + where + Self: Sized, + F: FnMut(Self::Item) -> Result, { Map { it: self, f: f } } @@ -337,8 +353,9 @@ pub trait FallibleIterator { /// underlying iterator. #[inline] fn map_err(self, f: F) -> MapErr - where F: FnMut(Self::Error) -> B, - Self: Sized + where + F: FnMut(Self::Error) -> B, + Self: Sized, { MapErr { it: self, f: f } } @@ -346,8 +363,9 @@ pub trait FallibleIterator { /// Returns the maximal element of the iterator. #[inline] fn max(mut self) -> Result, Self::Error> - where Self: Sized, - Self::Item: Ord + where + Self: Sized, + Self::Item: Ord, { let mut max = match try!(self.next()) { Some(v) => v, @@ -367,9 +385,10 @@ pub trait FallibleIterator { /// the function. The function may fail; such failures are returned to the caller. #[inline] fn max_by_key(mut self, mut f: F) -> Result, Self::Error> - where Self: Sized, - B: Ord, - F: FnMut(&Self::Item) -> Result + where + Self: Sized, + B: Ord, + F: FnMut(&Self::Item) -> Result, { let mut max = match try!(self.next()) { Some(v) => (f(&v)?, v), @@ -389,8 +408,9 @@ pub trait FallibleIterator { /// Returns the minimal element of the iterator. #[inline] fn min(mut self) -> Result, Self::Error> - where Self: Sized, - Self::Item: Ord + where + Self: Sized, + Self::Item: Ord, { let mut min = match try!(self.next()) { Some(v) => v, @@ -410,9 +430,10 @@ pub trait FallibleIterator { /// the function. The function may fail; such failures are returned to the caller. #[inline] fn min_by_key(mut self, mut f: F) -> Result, Self::Error> - where Self: Sized, - B: Ord, - F: FnMut(&Self::Item) -> Result + where + Self: Sized, + B: Ord, + F: FnMut(&Self::Item) -> Result, { let mut min = match try!(self.next()) { Some(v) => (f(&v)?, v), @@ -445,7 +466,8 @@ pub trait FallibleIterator { /// it. #[inline] fn peekable(self) -> Peekable - where Self: Sized + where + Self: Sized, { Peekable { it: self, @@ -458,8 +480,9 @@ pub trait FallibleIterator { /// caller. #[inline] fn position(&mut self, mut f: F) -> Result, Self::Error> - where Self: Sized, - F: FnMut(Self::Item) -> Result + where + Self: Sized, + F: FnMut(Self::Item) -> Result, { let mut i = 0; while let Some(v) = try!(self.next()) { @@ -475,7 +498,8 @@ pub trait FallibleIterator { /// order. #[inline] fn rev(self) -> Rev - where Self: Sized + DoubleEndedFallibleIterator + where + Self: Sized + DoubleEndedFallibleIterator, { Rev(self) } @@ -484,7 +508,8 @@ pub trait FallibleIterator { /// iterator. #[inline] fn take(self, n: usize) -> Take - where Self: Sized + where + Self: Sized, { Take { it: self, @@ -496,8 +521,9 @@ pub trait FallibleIterator { /// iterator's values. #[inline] fn zip(self, o: I) -> Zip - where Self: Sized, - I: IntoFallibleIterator + where + Self: Sized, + I: IntoFallibleIterator, { Zip(self, o.into_fallible_iterator()) } @@ -506,9 +532,10 @@ pub trait FallibleIterator { /// another. #[inline] fn cmp(mut self, other: I) -> Result - where Self: Sized, - I: IntoFallibleIterator, - Self::Item: Ord + where + Self: Sized, + I: IntoFallibleIterator, + Self::Item: Ord, { let mut other = other.into_fallible_iterator(); @@ -517,12 +544,10 @@ pub trait FallibleIterator { (None, None) => return Ok(Ordering::Equal), (None, _) => return Ok(Ordering::Less), (_, None) => return Ok(Ordering::Greater), - (Some(x), Some(y)) => { - match x.cmp(&y) { - Ordering::Equal => {} - o => return Ok(o), - } - } + (Some(x), Some(y)) => match x.cmp(&y) { + Ordering::Equal => {} + o => return Ok(o), + }, } } } @@ -531,9 +556,10 @@ pub trait FallibleIterator { /// another. #[inline] fn partial_cmp(mut self, other: I) -> Result, Self::Error> - where Self: Sized, - I: IntoFallibleIterator, - Self::Item: PartialOrd + where + Self: Sized, + I: IntoFallibleIterator, + Self::Item: PartialOrd, { let mut other = other.into_fallible_iterator(); @@ -542,12 +568,10 @@ pub trait FallibleIterator { (None, None) => return Ok(Some(Ordering::Equal)), (None, _) => return Ok(Some(Ordering::Less)), (_, None) => return Ok(Some(Ordering::Greater)), - (Some(x), Some(y)) => { - match x.partial_cmp(&y) { - Some(Ordering::Equal) => {} - o => return Ok(o), - } - } + (Some(x), Some(y)) => match x.partial_cmp(&y) { + Some(Ordering::Equal) => {} + o => return Ok(o), + }, } } } @@ -556,9 +580,10 @@ pub trait FallibleIterator { /// another. #[inline] fn eq(mut self, other: I) -> Result - where Self: Sized, - I: IntoFallibleIterator, - Self::Item: PartialEq + where + Self: Sized, + I: IntoFallibleIterator, + Self::Item: PartialEq, { let mut other = other.into_fallible_iterator(); @@ -579,9 +604,10 @@ pub trait FallibleIterator { /// another. #[inline] fn ne(mut self, other: I) -> Result - where Self: Sized, - I: IntoFallibleIterator, - Self::Item: PartialEq + where + Self: Sized, + I: IntoFallibleIterator, + Self::Item: PartialEq, { let mut other = other.into_fallible_iterator(); @@ -602,9 +628,10 @@ pub trait FallibleIterator { /// than those of another. #[inline] fn lt(mut self, other: I) -> Result - where Self: Sized, - I: IntoFallibleIterator, - Self::Item: PartialOrd + where + Self: Sized, + I: IntoFallibleIterator, + Self::Item: PartialOrd, { let mut other = other.into_fallible_iterator(); @@ -613,14 +640,12 @@ pub trait FallibleIterator { (None, None) => return Ok(false), (None, _) => return Ok(true), (_, None) => return Ok(false), - (Some(x), Some(y)) => { - match x.partial_cmp(&y) { - Some(Ordering::Less) => return Ok(true), - Some(Ordering::Equal) => {} - Some(Ordering::Greater) => return Ok(false), - None => return Ok(false), - } - } + (Some(x), Some(y)) => match x.partial_cmp(&y) { + Some(Ordering::Less) => return Ok(true), + Some(Ordering::Equal) => {} + Some(Ordering::Greater) => return Ok(false), + None => return Ok(false), + }, } } } @@ -629,9 +654,10 @@ pub trait FallibleIterator { /// than or equal to those of another. #[inline] fn le(mut self, other: I) -> Result - where Self: Sized, - I: IntoFallibleIterator, - Self::Item: PartialOrd + where + Self: Sized, + I: IntoFallibleIterator, + Self::Item: PartialOrd, { let mut other = other.into_fallible_iterator(); @@ -640,14 +666,12 @@ pub trait FallibleIterator { (None, None) => return Ok(true), (None, _) => return Ok(true), (_, None) => return Ok(false), - (Some(x), Some(y)) => { - match x.partial_cmp(&y) { - Some(Ordering::Less) => return Ok(true), - Some(Ordering::Equal) => {} - Some(Ordering::Greater) => return Ok(false), - None => return Ok(false), - } - } + (Some(x), Some(y)) => match x.partial_cmp(&y) { + Some(Ordering::Less) => return Ok(true), + Some(Ordering::Equal) => {} + Some(Ordering::Greater) => return Ok(false), + None => return Ok(false), + }, } } } @@ -656,9 +680,10 @@ pub trait FallibleIterator { /// greater than those of another. #[inline] fn gt(mut self, other: I) -> Result - where Self: Sized, - I: IntoFallibleIterator, - Self::Item: PartialOrd + where + Self: Sized, + I: IntoFallibleIterator, + Self::Item: PartialOrd, { let mut other = other.into_fallible_iterator(); @@ -667,14 +692,12 @@ pub trait FallibleIterator { (None, None) => return Ok(false), (None, _) => return Ok(false), (_, None) => return Ok(true), - (Some(x), Some(y)) => { - match x.partial_cmp(&y) { - Some(Ordering::Less) => return Ok(false), - Some(Ordering::Equal) => {} - Some(Ordering::Greater) => return Ok(true), - None => return Ok(false), - } - } + (Some(x), Some(y)) => match x.partial_cmp(&y) { + Some(Ordering::Less) => return Ok(false), + Some(Ordering::Equal) => {} + Some(Ordering::Greater) => return Ok(true), + None => return Ok(false), + }, } } } @@ -683,9 +706,10 @@ pub trait FallibleIterator { /// greater than or equal to those of another. #[inline] fn ge(mut self, other: I) -> Result - where Self: Sized, - I: IntoFallibleIterator, - Self::Item: PartialOrd + where + Self: Sized, + I: IntoFallibleIterator, + Self::Item: PartialOrd, { let mut other = other.into_fallible_iterator(); @@ -694,14 +718,12 @@ pub trait FallibleIterator { (None, None) => return Ok(true), (None, _) => return Ok(false), (_, None) => return Ok(true), - (Some(x), Some(y)) => { - match x.partial_cmp(&y) { - Some(Ordering::Less) => return Ok(false), - Some(Ordering::Equal) => {} - Some(Ordering::Greater) => return Ok(true), - None => return Ok(false), - } - } + (Some(x), Some(y)) => match x.partial_cmp(&y) { + Some(Ordering::Less) => return Ok(false), + Some(Ordering::Equal) => {} + Some(Ordering::Greater) => return Ok(true), + None => return Ok(false), + }, } } } @@ -763,14 +785,16 @@ pub trait DoubleEndedFallibleIterator: FallibleIterator { pub trait FromFallibleIterator: Sized { /// Creates a value from a fallible iterator. fn from_fallible_iterator(it: I) -> Result - where I: FallibleIterator; + where + I: FallibleIterator; } #[cfg(any(feature = "std", feature = "alloc"))] impl FromFallibleIterator for Vec { #[inline] fn from_fallible_iterator(mut it: I) -> Result, I::Error> - where I: FallibleIterator + where + I: FallibleIterator, { let mut vec = Vec::with_capacity(it.size_hint().0); while let Some(v) = try!(it.next()) { @@ -782,11 +806,13 @@ impl FromFallibleIterator for Vec { #[cfg(feature = "std")] impl FromFallibleIterator for HashSet - where T: Hash + Eq +where + T: Hash + Eq, { #[inline] fn from_fallible_iterator(mut it: I) -> Result, I::Error> - where I: FallibleIterator + where + I: FallibleIterator, { let mut set = HashSet::with_capacity(it.size_hint().0); while let Some(v) = try!(it.next()) { @@ -798,11 +824,13 @@ impl FromFallibleIterator for HashSet #[cfg(feature = "std")] impl FromFallibleIterator<(K, V)> for HashMap - where K: Hash + Eq +where + K: Hash + Eq, { #[inline] fn from_fallible_iterator(mut it: I) -> Result, I::Error> - where I: FallibleIterator + where + I: FallibleIterator, { let mut map = HashMap::with_capacity(it.size_hint().0); while let Some((k, v)) = try!(it.next()) { @@ -814,11 +842,13 @@ impl FromFallibleIterator<(K, V)> for HashMap #[cfg(any(feature = "std", feature = "alloc"))] impl FromFallibleIterator for BTreeSet - where T: Ord +where + T: Ord, { #[inline] fn from_fallible_iterator(mut it: I) -> Result, I::Error> - where I: FallibleIterator + where + I: FallibleIterator, { let mut set = BTreeSet::new(); while let Some(v) = try!(it.next()) { @@ -830,11 +860,13 @@ impl FromFallibleIterator for BTreeSet #[cfg(any(feature = "std", feature = "alloc"))] impl FromFallibleIterator<(K, V)> for BTreeMap - where K: Ord +where + K: Ord, { #[inline] fn from_fallible_iterator(mut it: I) -> Result, I::Error> - where I: FallibleIterator + where + I: FallibleIterator, { let mut map = BTreeMap::new(); while let Some((k, v)) = try!(it.next()) { @@ -860,7 +892,8 @@ pub trait IntoFallibleIterator { } impl IntoFallibleIterator for I - where I: FallibleIterator +where + I: FallibleIterator, { type Item = I::Item; type Error = I::Error; @@ -881,8 +914,9 @@ pub struct Map { } impl FallibleIterator for Map - where T: FallibleIterator, - F: FnMut(T::Item) -> Result +where + T: FallibleIterator, + F: FnMut(T::Item) -> Result, { type Item = B; type Error = T::Error; @@ -903,8 +937,9 @@ impl FallibleIterator for Map } impl DoubleEndedFallibleIterator for Map - where I: DoubleEndedFallibleIterator, - F: FnMut(I::Item) -> Result +where + I: DoubleEndedFallibleIterator, + F: FnMut(I::Item) -> Result, { #[inline] fn next_back(&mut self) -> Result, I::Error> { @@ -932,8 +967,9 @@ pub struct Chain { } impl FallibleIterator for Chain - where T: FallibleIterator, - U: FallibleIterator +where + T: FallibleIterator, + U: FallibleIterator, { type Item = T::Item; type Error = T::Error; @@ -941,15 +977,13 @@ impl FallibleIterator for Chain #[inline] fn next(&mut self) -> Result, T::Error> { match self.state { - ChainState::Both => { - match try!(self.front.next()) { - Some(e) => Ok(Some(e)), - None => { - self.state = ChainState::Back; - self.back.next() - } + ChainState::Both => match try!(self.front.next()) { + Some(e) => Ok(Some(e)), + None => { + self.state = ChainState::Back; + self.back.next() } - } + }, ChainState::Front => self.front.next(), ChainState::Back => self.back.next(), } @@ -980,21 +1014,20 @@ impl FallibleIterator for Chain } impl DoubleEndedFallibleIterator for Chain - where T: DoubleEndedFallibleIterator, - U: DoubleEndedFallibleIterator +where + T: DoubleEndedFallibleIterator, + U: DoubleEndedFallibleIterator, { #[inline] fn next_back(&mut self) -> Result, T::Error> { match self.state { - ChainState::Both => { - match try!(self.back.next_back()) { - Some(e) => Ok(Some(e)), - None => { - self.state = ChainState::Front; - self.front.next_back() - } + ChainState::Both => match try!(self.back.next_back()) { + Some(e) => Ok(Some(e)), + None => { + self.state = ChainState::Front; + self.front.next_back() } - } + }, ChainState::Front => self.front.next_back(), ChainState::Back => self.back.next_back(), } @@ -1006,8 +1039,9 @@ impl DoubleEndedFallibleIterator for Chain pub struct Cloned(I); impl<'a, T, I> FallibleIterator for Cloned - where I: FallibleIterator, - T: 'a + Clone +where + I: FallibleIterator, + T: 'a + Clone, { type Item = T; type Error = I::Error; @@ -1029,8 +1063,9 @@ impl<'a, T, I> FallibleIterator for Cloned } impl<'a, T, I> DoubleEndedFallibleIterator for Cloned - where I: DoubleEndedFallibleIterator, - T: 'a + Clone +where + I: DoubleEndedFallibleIterator, + T: 'a + Clone, { #[inline] fn next_back(&mut self) -> Result, I::Error> { @@ -1041,7 +1076,8 @@ impl<'a, T, I> DoubleEndedFallibleIterator for Cloned /// Converts an `Iterator>` into a `FallibleIterator`. #[inline] pub fn convert(it: I) -> Convert - where I: iter::Iterator> +where + I: iter::Iterator>, { Convert(it) } @@ -1051,7 +1087,8 @@ pub fn convert(it: I) -> Convert pub struct Convert(I); impl FallibleIterator for Convert - where I: iter::Iterator> +where + I: iter::Iterator>, { type Item = T; type Error = E; @@ -1072,7 +1109,8 @@ impl FallibleIterator for Convert } impl DoubleEndedFallibleIterator for Convert - where I: DoubleEndedIterator> +where + I: DoubleEndedIterator>, { #[inline] fn next_back(&mut self) -> Result, E> { @@ -1093,22 +1131,21 @@ pub struct Enumerate { } impl FallibleIterator for Enumerate - where I: FallibleIterator +where + I: FallibleIterator, { type Item = (usize, I::Item); type Error = I::Error; #[inline] fn next(&mut self) -> Result, I::Error> { - self.it - .next() - .map(|o| { - o.map(|e| { - let i = self.n; - self.n += 1; - (i, e) - }) + self.it.next().map(|o| { + o.map(|e| { + let i = self.n; + self.n += 1; + (i, e) }) + }) } #[inline] @@ -1131,8 +1168,9 @@ pub struct Filter { } impl FallibleIterator for Filter - where I: FallibleIterator, - F: FnMut(&I::Item) -> Result +where + I: FallibleIterator, + F: FnMut(&I::Item) -> Result, { type Item = I::Item; type Error = I::Error; @@ -1155,8 +1193,9 @@ impl FallibleIterator for Filter } impl DoubleEndedFallibleIterator for Filter - where I: DoubleEndedFallibleIterator, - F: FnMut(&I::Item) -> Result +where + I: DoubleEndedFallibleIterator, + F: FnMut(&I::Item) -> Result, { #[inline] fn next_back(&mut self) -> Result, I::Error> { @@ -1179,8 +1218,9 @@ pub struct FilterMap { } impl FallibleIterator for FilterMap - where I: FallibleIterator, - F: FnMut(I::Item) -> Result, I::Error> +where + I: FallibleIterator, + F: FnMut(I::Item) -> Result, I::Error>, { type Item = B; type Error = I::Error; @@ -1203,8 +1243,9 @@ impl FallibleIterator for FilterMap } impl DoubleEndedFallibleIterator for FilterMap - where I: DoubleEndedFallibleIterator, - F: FnMut(I::Item) -> Result, I::Error> +where + I: DoubleEndedFallibleIterator, + F: FnMut(I::Item) -> Result, I::Error>, { #[inline] fn next_back(&mut self) -> Result, I::Error> { @@ -1227,7 +1268,8 @@ pub struct Fuse { } impl FallibleIterator for Fuse - where I: FallibleIterator +where + I: FallibleIterator, { type Item = I::Item; type Error = I::Error; @@ -1268,7 +1310,8 @@ impl FallibleIterator for Fuse pub struct Iterator(I); impl iter::Iterator for Iterator - where I: FallibleIterator +where + I: FallibleIterator, { type Item = Result; @@ -1288,7 +1331,8 @@ impl iter::Iterator for Iterator } impl DoubleEndedIterator for Iterator - where I: DoubleEndedFallibleIterator +where + I: DoubleEndedFallibleIterator, { #[inline] fn next_back(&mut self) -> Option> { @@ -1309,8 +1353,9 @@ pub struct MapErr { } impl FallibleIterator for MapErr - where I: FallibleIterator, - F: FnMut(I::Error) -> B +where + I: FallibleIterator, + F: FnMut(I::Error) -> B, { type Item = I::Item; type Error = B; @@ -1332,8 +1377,9 @@ impl FallibleIterator for MapErr } impl DoubleEndedFallibleIterator for MapErr - where I: DoubleEndedFallibleIterator, - F: FnMut(I::Error) -> B +where + I: DoubleEndedFallibleIterator, + F: FnMut(I::Error) -> B, { #[inline] fn next_back(&mut self) -> Result, B> { @@ -1349,7 +1395,8 @@ pub struct Peekable { } impl Peekable - where I: FallibleIterator +where + I: FallibleIterator, { /// Returns a reference to the next value without advancing the iterator. #[inline] @@ -1363,7 +1410,8 @@ impl Peekable } impl FallibleIterator for Peekable - where I: FallibleIterator +where + I: FallibleIterator, { type Item = I::Item; type Error = I::Error; @@ -1394,7 +1442,8 @@ impl FallibleIterator for Peekable pub struct Rev(I); impl FallibleIterator for Rev - where I: DoubleEndedFallibleIterator +where + I: DoubleEndedFallibleIterator, { type Item = I::Item; type Error = I::Error; @@ -1416,7 +1465,8 @@ impl FallibleIterator for Rev } impl DoubleEndedFallibleIterator for Rev - where I: DoubleEndedFallibleIterator +where + I: DoubleEndedFallibleIterator, { #[inline] fn next_back(&mut self) -> Result, I::Error> { @@ -1433,7 +1483,8 @@ pub struct Take { } impl FallibleIterator for Take - where I: FallibleIterator +where + I: FallibleIterator, { type Item = I::Item; type Error = I::Error; @@ -1454,7 +1505,10 @@ impl FallibleIterator for Take #[inline] fn size_hint(&self) -> (usize, Option) { let hint = self.it.size_hint(); - (cmp::min(hint.0, self.remaining), hint.1.map(|n| cmp::min(n, self.remaining))) + ( + cmp::min(hint.0, self.remaining), + hint.1.map(|n| cmp::min(n, self.remaining)), + ) } } @@ -1464,8 +1518,9 @@ impl FallibleIterator for Take pub struct Zip(T, U); impl FallibleIterator for Zip - where T: FallibleIterator, - U: FallibleIterator +where + T: FallibleIterator, + U: FallibleIterator, { type Item = (T::Item, U::Item); type Error = T::Error; From 7a54eea255de9e7a48eeeaf80786b703b6291bcd Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 19 Sep 2018 20:53:52 -0700 Subject: [PATCH 08/34] try! -> ? --- src/lib.rs | 84 +++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 610ec79..bb40f35 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ //! //! ```ignore //! for line in reader.lines() { -//! let line = try!(line); +//! let line = line?; //! // work with line //! } //! ``` @@ -38,7 +38,7 @@ //! loop syntax, but `while let` loops offer a similar level of ergonomics: //! //! ```ignore -//! while let Some(item) = try!(iter.next()) { +//! while let Some(item) = iter.next()? { //! // work with item //! } //! ``` @@ -144,7 +144,7 @@ pub trait FallibleIterator { Self: Sized, F: FnMut(Self::Item) -> Result, { - while let Some(v) = try!(self.next()) { + while let Some(v) = self.next()? { if !f(v)? { return Ok(false); } @@ -161,7 +161,7 @@ pub trait FallibleIterator { Self: Sized, F: FnMut(Self::Item) -> Result, { - while let Some(v) = try!(self.next()) { + while let Some(v) = self.next()? { if f(v)? { return Ok(true); } @@ -214,7 +214,7 @@ pub trait FallibleIterator { Self: Sized, { let mut count = 0; - while let Some(_) = try!(self.next()) { + while let Some(_) = self.next()? { count += 1; } @@ -274,7 +274,7 @@ pub trait FallibleIterator { Self: Sized, F: FnMut(&Self::Item) -> Result, { - while let Some(v) = try!(self.next()) { + while let Some(v) = self.next()? { if f(&v)? { return Ok(Some(v)); } @@ -309,7 +309,7 @@ pub trait FallibleIterator { Self: Sized, F: FnMut(B, Self::Item) -> Result, { - while let Some(v) = try!(self.next()) { + while let Some(v) = self.next()? { init = f(init, v)?; } @@ -332,7 +332,7 @@ pub trait FallibleIterator { Self: Sized, { let mut last = None; - while let Some(e) = try!(self.next()) { + while let Some(e) = self.next()? { last = Some(e); } Ok(last) @@ -367,12 +367,12 @@ pub trait FallibleIterator { Self: Sized, Self::Item: Ord, { - let mut max = match try!(self.next()) { + let mut max = match self.next()? { Some(v) => v, None => return Ok(None), }; - while let Some(v) = try!(self.next()) { + while let Some(v) = self.next()? { if max < v { max = v; } @@ -390,12 +390,12 @@ pub trait FallibleIterator { B: Ord, F: FnMut(&Self::Item) -> Result, { - let mut max = match try!(self.next()) { + let mut max = match self.next()? { Some(v) => (f(&v)?, v), None => return Ok(None), }; - while let Some(v) = try!(self.next()) { + while let Some(v) = self.next()? { let b = f(&v)?; if max.0 < b { max = (b, v); @@ -412,12 +412,12 @@ pub trait FallibleIterator { Self: Sized, Self::Item: Ord, { - let mut min = match try!(self.next()) { + let mut min = match self.next()? { Some(v) => v, None => return Ok(None), }; - while let Some(v) = try!(self.next()) { + while let Some(v) = self.next()? { if min > v { min = v; } @@ -435,12 +435,12 @@ pub trait FallibleIterator { B: Ord, F: FnMut(&Self::Item) -> Result, { - let mut min = match try!(self.next()) { + let mut min = match self.next()? { Some(v) => (f(&v)?, v), None => return Ok(None), }; - while let Some(v) = try!(self.next()) { + while let Some(v) = self.next()? { let b = f(&v)?; if min.0 > b { min = (b, v); @@ -453,7 +453,7 @@ pub trait FallibleIterator { /// Returns the `n`th element of the iterator. #[inline] fn nth(&mut self, mut n: usize) -> Result, Self::Error> { - while let Some(e) = try!(self.next()) { + while let Some(e) = self.next()? { if n == 0 { return Ok(Some(e)); } @@ -485,7 +485,7 @@ pub trait FallibleIterator { F: FnMut(Self::Item) -> Result, { let mut i = 0; - while let Some(v) = try!(self.next()) { + while let Some(v) = self.next()? { if f(v)? { return Ok(Some(i)); } @@ -540,7 +540,7 @@ pub trait FallibleIterator { let mut other = other.into_fallible_iterator(); loop { - match (try!(self.next()), try!(other.next())) { + match (self.next()?, other.next()?) { (None, None) => return Ok(Ordering::Equal), (None, _) => return Ok(Ordering::Less), (_, None) => return Ok(Ordering::Greater), @@ -564,7 +564,7 @@ pub trait FallibleIterator { let mut other = other.into_fallible_iterator(); loop { - match (try!(self.next()), try!(other.next())) { + match (self.next()?, other.next()?) { (None, None) => return Ok(Some(Ordering::Equal)), (None, _) => return Ok(Some(Ordering::Less)), (_, None) => return Ok(Some(Ordering::Greater)), @@ -588,7 +588,7 @@ pub trait FallibleIterator { let mut other = other.into_fallible_iterator(); loop { - match (try!(self.next()), try!(other.next())) { + match (self.next()?, other.next()?) { (None, None) => return Ok(true), (None, _) | (_, None) => return Ok(false), (Some(x), Some(y)) => { @@ -612,7 +612,7 @@ pub trait FallibleIterator { let mut other = other.into_fallible_iterator(); loop { - match (try!(self.next()), try!(other.next())) { + match (self.next()?, other.next()?) { (None, None) => return Ok(false), (None, _) | (_, None) => return Ok(true), (Some(x), Some(y)) => { @@ -636,7 +636,7 @@ pub trait FallibleIterator { let mut other = other.into_fallible_iterator(); loop { - match (try!(self.next()), try!(other.next())) { + match (self.next()?, other.next()?) { (None, None) => return Ok(false), (None, _) => return Ok(true), (_, None) => return Ok(false), @@ -662,7 +662,7 @@ pub trait FallibleIterator { let mut other = other.into_fallible_iterator(); loop { - match (try!(self.next()), try!(other.next())) { + match (self.next()?, other.next()?) { (None, None) => return Ok(true), (None, _) => return Ok(true), (_, None) => return Ok(false), @@ -688,7 +688,7 @@ pub trait FallibleIterator { let mut other = other.into_fallible_iterator(); loop { - match (try!(self.next()), try!(other.next())) { + match (self.next()?, other.next()?) { (None, None) => return Ok(false), (None, _) => return Ok(false), (_, None) => return Ok(true), @@ -714,7 +714,7 @@ pub trait FallibleIterator { let mut other = other.into_fallible_iterator(); loop { - match (try!(self.next()), try!(other.next())) { + match (self.next()?, other.next()?) { (None, None) => return Ok(true), (None, _) => return Ok(false), (_, None) => return Ok(true), @@ -797,7 +797,7 @@ impl FromFallibleIterator for Vec { I: FallibleIterator, { let mut vec = Vec::with_capacity(it.size_hint().0); - while let Some(v) = try!(it.next()) { + while let Some(v) = it.next()? { vec.push(v); } Ok(vec) @@ -815,7 +815,7 @@ where I: FallibleIterator, { let mut set = HashSet::with_capacity(it.size_hint().0); - while let Some(v) = try!(it.next()) { + while let Some(v) = it.next()? { set.insert(v); } Ok(set) @@ -833,7 +833,7 @@ where I: FallibleIterator, { let mut map = HashMap::with_capacity(it.size_hint().0); - while let Some((k, v)) = try!(it.next()) { + while let Some((k, v)) = it.next()? { map.insert(k, v); } Ok(map) @@ -851,7 +851,7 @@ where I: FallibleIterator, { let mut set = BTreeSet::new(); - while let Some(v) = try!(it.next()) { + while let Some(v) = it.next()? { set.insert(v); } Ok(set) @@ -869,7 +869,7 @@ where I: FallibleIterator, { let mut map = BTreeMap::new(); - while let Some((k, v)) = try!(it.next()) { + while let Some((k, v)) = it.next()? { map.insert(k, v); } Ok(map) @@ -924,7 +924,7 @@ where #[inline] fn next(&mut self) -> Result, T::Error> { match self.it.next() { - Ok(Some(v)) => Ok(Some(try!((self.f)(v)))), + Ok(Some(v)) => Ok(Some((self.f)(v)?)), Ok(None) => Ok(None), Err(e) => Err(e), } @@ -944,7 +944,7 @@ where #[inline] fn next_back(&mut self) -> Result, I::Error> { match self.it.next_back() { - Ok(Some(v)) => Ok(Some(try!((self.f)(v)))), + Ok(Some(v)) => Ok(Some((self.f)(v)?)), Ok(None) => Ok(None), Err(e) => Err(e), } @@ -977,7 +977,7 @@ where #[inline] fn next(&mut self) -> Result, T::Error> { match self.state { - ChainState::Both => match try!(self.front.next()) { + ChainState::Both => match self.front.next()? { Some(e) => Ok(Some(e)), None => { self.state = ChainState::Back; @@ -1006,7 +1006,7 @@ where #[inline] fn count(self) -> Result { match self.state { - ChainState::Both => Ok(try!(self.front.count()) + try!(self.back.count())), + ChainState::Both => Ok(self.front.count()? + self.back.count()?), ChainState::Front => self.front.count(), ChainState::Back => self.back.count(), } @@ -1021,7 +1021,7 @@ where #[inline] fn next_back(&mut self) -> Result, T::Error> { match self.state { - ChainState::Both => match try!(self.back.next_back()) { + ChainState::Both => match self.back.next_back()? { Some(e) => Ok(Some(e)), None => { self.state = ChainState::Front; @@ -1177,7 +1177,7 @@ where #[inline] fn next(&mut self) -> Result, I::Error> { - while let Some(v) = try!(self.it.next()) { + while let Some(v) = self.it.next()? { if (self.f)(&v)? { return Ok(Some(v)); } @@ -1199,7 +1199,7 @@ where { #[inline] fn next_back(&mut self) -> Result, I::Error> { - while let Some(v) = try!(self.it.next_back()) { + while let Some(v) = self.it.next_back()? { if (self.f)(&v)? { return Ok(Some(v)); } @@ -1227,7 +1227,7 @@ where #[inline] fn next(&mut self) -> Result, I::Error> { - while let Some(v) = try!(self.it.next()) { + while let Some(v) = self.it.next()? { if let Some(v) = (self.f)(v)? { return Ok(Some(v)); } @@ -1249,7 +1249,7 @@ where { #[inline] fn next_back(&mut self) -> Result, I::Error> { - while let Some(v) = try!(self.it.next_back()) { + while let Some(v) = self.it.next_back()? { if let Some(v) = (self.f)(v)? { return Ok(Some(v)); } @@ -1402,7 +1402,7 @@ where #[inline] pub fn peek(&mut self) -> Result, I::Error> { if self.next.is_none() { - self.next = try!(self.it.next()); + self.next = self.it.next()?; } Ok(self.next.as_ref()) @@ -1527,7 +1527,7 @@ where #[inline] fn next(&mut self) -> Result, T::Error> { - match (try!(self.0.next()), try!(self.1.next())) { + match (self.0.next()?, self.1.next()?) { (Some(a), Some(b)) => Ok(Some((a, b))), _ => Ok(None), } From 32d8fd028d1e824ddc34dc154a68c44e7b34d4d5 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 19 Sep 2018 21:06:16 -0700 Subject: [PATCH 09/34] Reorder methods to match Iterator --- src/lib.rs | 344 ++++++++++++++++++++++++++--------------------------- 1 file changed, 172 insertions(+), 172 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index bb40f35..4657c48 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -136,50 +136,43 @@ pub trait FallibleIterator { (0, None) } - /// Determines if all elements of this iterator match a predicate. - /// The predicate may fail; such failures are passed to the caller. + /// Consumes the iterator, returning the number of remaining items. #[inline] - fn all(&mut self, mut f: F) -> Result + fn count(mut self) -> Result where Self: Sized, - F: FnMut(Self::Item) -> Result, { - while let Some(v) = self.next()? { - if !f(v)? { - return Ok(false); - } + let mut count = 0; + while let Some(_) = self.next()? { + count += 1; } - Ok(true) + Ok(count) } - /// Determines if any element of this iterator matches a predicate. - /// The predicate may fail; such failures are passed to the caller. + /// Returns the last element of the iterator. #[inline] - fn any(&mut self, mut f: F) -> Result + fn last(mut self) -> Result, Self::Error> where Self: Sized, - F: FnMut(Self::Item) -> Result, { - while let Some(v) = self.next()? { - if f(v)? { - return Ok(true); - } + let mut last = None; + while let Some(e) = self.next()? { + last = Some(e); } - - Ok(false) + Ok(last) } - /// Borrow an iterator rather than consuming it. - /// - /// This is useful to allow the use of iterator adaptors that would - /// otherwise consume the value. + /// Returns the `n`th element of the iterator. #[inline] - fn by_ref(&mut self) -> &mut Self - where - Self: Sized, - { - self + fn nth(&mut self, mut n: usize) -> Result, Self::Error> { + while let Some(e) = self.next()? { + if n == 0 { + return Ok(Some(e)); + } + n -= 1; + } + Ok(None) } /// Returns an iterator which yields the elements of this iterator followed @@ -197,50 +190,26 @@ pub trait FallibleIterator { } } - /// Returns an iterator which clones all of its elements. - #[inline] - fn cloned<'a, T>(self) -> Cloned - where - Self: Sized + FallibleIterator, - T: 'a + Clone, - { - Cloned(self) - } - - /// Consumes the iterator, returning the number of remaining items. - #[inline] - fn count(mut self) -> Result - where - Self: Sized, - { - let mut count = 0; - while let Some(_) = self.next()? { - count += 1; - } - - Ok(count) - } - - /// Transforms the iterator into a collection. - /// - /// An `Err` will be returned if any invocation of `next` returns `Err`. + /// Returns an iterator that yields pairs of this iterator's and another + /// iterator's values. #[inline] - fn collect(self) -> Result + fn zip(self, o: I) -> Zip where - T: FromFallibleIterator, Self: Sized, + I: IntoFallibleIterator, { - T::from_fallible_iterator(self) + Zip(self, o.into_fallible_iterator()) } - /// Returns an iterator which yields the current iteration count as well - /// as the value. + /// Returns an iterator which applies a fallible transform to the elements + /// of the underlying iterator. #[inline] - fn enumerate(self) -> Enumerate + fn map(self, f: F) -> Map where Self: Sized, + F: FnMut(Self::Item) -> Result, { - Enumerate { it: self, n: 0 } + Map { it: self, f: f } } /// Returns an iterator which uses a predicate to determine which values @@ -266,21 +235,40 @@ pub trait FallibleIterator { FilterMap { it: self, f: f } } - /// Returns the first element of the iterator that matches a predicate. - /// The predicate may fail; such failures are passed along to the caller. + /// Returns an iterator which yields the current iteration count as well + /// as the value. #[inline] - fn find(&mut self, mut f: F) -> Result, Self::Error> + fn enumerate(self) -> Enumerate where Self: Sized, - F: FnMut(&Self::Item) -> Result, { - while let Some(v) = self.next()? { - if f(&v)? { - return Ok(Some(v)); - } + Enumerate { it: self, n: 0 } + } + + /// Returns an iterator that can peek at the next element without consuming + /// it. + #[inline] + fn peekable(self) -> Peekable + where + Self: Sized, + { + Peekable { + it: self, + next: None, } + } - Ok(None) + /// Returns an iterator that yields only the first `n` values of this + /// iterator. + #[inline] + fn take(self, n: usize) -> Take + where + Self: Sized, + { + Take { + it: self, + remaining: n, + } } /// Returns an iterator which yields this iterator's elements and ends after @@ -300,6 +288,30 @@ pub trait FallibleIterator { } } + /// Borrow an iterator rather than consuming it. + /// + /// This is useful to allow the use of iterator adaptors that would + /// otherwise consume the value. + #[inline] + fn by_ref(&mut self) -> &mut Self + where + Self: Sized, + { + self + } + + /// Transforms the iterator into a collection. + /// + /// An `Err` will be returned if any invocation of `next` returns `Err`. + #[inline] + fn collect(self) -> Result + where + T: FromFallibleIterator, + Self: Sized, + { + T::from_fallible_iterator(self) + } + /// Applies a function over the elements of the iterator, producing a single /// final value. The function may fail; such failures are returned to the /// caller. @@ -316,48 +328,74 @@ pub trait FallibleIterator { Ok(init) } - /// Returns a normal (non-fallible) iterator over `Result`. + /// Determines if all elements of this iterator match a predicate. + /// The predicate may fail; such failures are passed to the caller. #[inline] - fn iterator(self) -> Iterator + fn all(&mut self, mut f: F) -> Result where Self: Sized, + F: FnMut(Self::Item) -> Result, { - Iterator(self) + while let Some(v) = self.next()? { + if !f(v)? { + return Ok(false); + } + } + + Ok(true) } - /// Returns the last element of the iterator. + /// Determines if any element of this iterator matches a predicate. + /// The predicate may fail; such failures are passed to the caller. #[inline] - fn last(mut self) -> Result, Self::Error> + fn any(&mut self, mut f: F) -> Result where Self: Sized, + F: FnMut(Self::Item) -> Result, { - let mut last = None; - while let Some(e) = self.next()? { - last = Some(e); + while let Some(v) = self.next()? { + if f(v)? { + return Ok(true); + } } - Ok(last) + + Ok(false) } - /// Returns an iterator which applies a fallible transform to the elements - /// of the underlying iterator. + /// Returns the first element of the iterator that matches a predicate. + /// The predicate may fail; such failures are passed along to the caller. #[inline] - fn map(self, f: F) -> Map + fn find(&mut self, mut f: F) -> Result, Self::Error> where Self: Sized, - F: FnMut(Self::Item) -> Result, + F: FnMut(&Self::Item) -> Result, { - Map { it: self, f: f } + while let Some(v) = self.next()? { + if f(&v)? { + return Ok(Some(v)); + } + } + + Ok(None) } - /// Returns an iterator which applies a transform to the errors of the - /// underlying iterator. + /// Returns the position of the first element of this iterator that matches + /// a predicate. The predicate may fail; such failures are returned to the + /// caller. #[inline] - fn map_err(self, f: F) -> MapErr + fn position(&mut self, mut f: F) -> Result, Self::Error> where - F: FnMut(Self::Error) -> B, Self: Sized, + F: FnMut(Self::Item) -> Result, { - MapErr { it: self, f: f } + let mut i = 0; + while let Some(v) = self.next()? { + if f(v)? { + return Ok(Some(i)); + } + i += 1; + } + Ok(None) } /// Returns the maximal element of the iterator. @@ -381,49 +419,49 @@ pub trait FallibleIterator { Ok(Some(max)) } - /// Returns the element of the iterator which gives the maximum value from - /// the function. The function may fail; such failures are returned to the caller. + /// Returns the minimal element of the iterator. #[inline] - fn max_by_key(mut self, mut f: F) -> Result, Self::Error> + fn min(mut self) -> Result, Self::Error> where Self: Sized, - B: Ord, - F: FnMut(&Self::Item) -> Result, + Self::Item: Ord, { - let mut max = match self.next()? { - Some(v) => (f(&v)?, v), + let mut min = match self.next()? { + Some(v) => v, None => return Ok(None), }; while let Some(v) = self.next()? { - let b = f(&v)?; - if max.0 < b { - max = (b, v); + if min > v { + min = v; } } - Ok(Some(max.1)) + Ok(Some(min)) } - /// Returns the minimal element of the iterator. + /// Returns the element of the iterator which gives the maximum value from + /// the function. The function may fail; such failures are returned to the caller. #[inline] - fn min(mut self) -> Result, Self::Error> + fn max_by_key(mut self, mut f: F) -> Result, Self::Error> where Self: Sized, - Self::Item: Ord, + B: Ord, + F: FnMut(&Self::Item) -> Result, { - let mut min = match self.next()? { - Some(v) => v, + let mut max = match self.next()? { + Some(v) => (f(&v)?, v), None => return Ok(None), }; while let Some(v) = self.next()? { - if min > v { - min = v; + let b = f(&v)?; + if max.0 < b { + max = (b, v); } } - Ok(Some(min)) + Ok(Some(max.1)) } /// Returns the element of the iterator which gives the minimum value from @@ -450,50 +488,6 @@ pub trait FallibleIterator { Ok(Some(min.1)) } - /// Returns the `n`th element of the iterator. - #[inline] - fn nth(&mut self, mut n: usize) -> Result, Self::Error> { - while let Some(e) = self.next()? { - if n == 0 { - return Ok(Some(e)); - } - n -= 1; - } - Ok(None) - } - - /// Returns an iterator that can peek at the next element without consuming - /// it. - #[inline] - fn peekable(self) -> Peekable - where - Self: Sized, - { - Peekable { - it: self, - next: None, - } - } - - /// Returns the position of the first element of this iterator that matches - /// a predicate. The predicate may fail; such failures are returned to the - /// caller. - #[inline] - fn position(&mut self, mut f: F) -> Result, Self::Error> - where - Self: Sized, - F: FnMut(Self::Item) -> Result, - { - let mut i = 0; - while let Some(v) = self.next()? { - if f(v)? { - return Ok(Some(i)); - } - i += 1; - } - Ok(None) - } - /// Returns an iterator that yields this iterator's items in the opposite /// order. #[inline] @@ -504,28 +498,14 @@ pub trait FallibleIterator { Rev(self) } - /// Returns an iterator that yields only the first `n` values of this - /// iterator. - #[inline] - fn take(self, n: usize) -> Take - where - Self: Sized, - { - Take { - it: self, - remaining: n, - } - } - - /// Returns an iterator that yields pairs of this iterator's and another - /// iterator's values. + /// Returns an iterator which clones all of its elements. #[inline] - fn zip(self, o: I) -> Zip + fn cloned<'a, T>(self) -> Cloned where - Self: Sized, - I: IntoFallibleIterator, + Self: Sized + FallibleIterator, + T: 'a + Clone, { - Zip(self, o.into_fallible_iterator()) + Cloned(self) } /// Lexicographically compares the elements of this iterator to that of @@ -727,6 +707,26 @@ pub trait FallibleIterator { } } } + + /// Returns a normal (non-fallible) iterator over `Result`. + #[inline] + fn iterator(self) -> Iterator + where + Self: Sized, + { + Iterator(self) + } + + /// Returns an iterator which applies a transform to the errors of the + /// underlying iterator. + #[inline] + fn map_err(self, f: F) -> MapErr + where + F: FnMut(Self::Error) -> B, + Self: Sized, + { + MapErr { it: self, f: f } + } } impl<'a, I: FallibleIterator + ?Sized> FallibleIterator for &'a mut I { From 39c7dcb6bb7c2bd87acc77cdf6e935bc19a681c6 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 19 Sep 2018 21:11:21 -0700 Subject: [PATCH 10/34] Make FromFallibleIterator take IntoFallibleIterators Closes #9 --- src/lib.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4657c48..358c4be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -786,16 +786,17 @@ pub trait FromFallibleIterator: Sized { /// Creates a value from a fallible iterator. fn from_fallible_iterator(it: I) -> Result where - I: FallibleIterator; + I: IntoFallibleIterator; } #[cfg(any(feature = "std", feature = "alloc"))] impl FromFallibleIterator for Vec { #[inline] - fn from_fallible_iterator(mut it: I) -> Result, I::Error> + fn from_fallible_iterator(it: I) -> Result, I::Error> where - I: FallibleIterator, + I: IntoFallibleIterator, { + let mut it = it.into_fallible_iterator(); let mut vec = Vec::with_capacity(it.size_hint().0); while let Some(v) = it.next()? { vec.push(v); @@ -810,10 +811,11 @@ where T: Hash + Eq, { #[inline] - fn from_fallible_iterator(mut it: I) -> Result, I::Error> + fn from_fallible_iterator(it: I) -> Result, I::Error> where - I: FallibleIterator, + I: IntoFallibleIterator, { + let mut it = it.into_fallible_iterator(); let mut set = HashSet::with_capacity(it.size_hint().0); while let Some(v) = it.next()? { set.insert(v); @@ -828,10 +830,11 @@ where K: Hash + Eq, { #[inline] - fn from_fallible_iterator(mut it: I) -> Result, I::Error> + fn from_fallible_iterator(it: I) -> Result, I::Error> where - I: FallibleIterator, + I: IntoFallibleIterator, { + let mut it = it.into_fallible_iterator(); let mut map = HashMap::with_capacity(it.size_hint().0); while let Some((k, v)) = it.next()? { map.insert(k, v); @@ -846,10 +849,11 @@ where T: Ord, { #[inline] - fn from_fallible_iterator(mut it: I) -> Result, I::Error> + fn from_fallible_iterator(it: I) -> Result, I::Error> where - I: FallibleIterator, + I: IntoFallibleIterator, { + let mut it = it.into_fallible_iterator(); let mut set = BTreeSet::new(); while let Some(v) = it.next()? { set.insert(v); @@ -864,10 +868,11 @@ where K: Ord, { #[inline] - fn from_fallible_iterator(mut it: I) -> Result, I::Error> + fn from_fallible_iterator(it: I) -> Result, I::Error> where - I: FallibleIterator, + I: IntoFallibleIterator, { + let mut it = it.into_fallible_iterator(); let mut map = BTreeMap::new(); while let Some((k, v)) = it.next()? { map.insert(k, v); From 0ecc5cf79ca9f2f8d699b7ac55da12f93ae8465b Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 20 Sep 2018 20:24:20 -0700 Subject: [PATCH 11/34] Implement step_by --- src/lib.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/test.rs | 6 ++++++ 2 files changed, 68 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 358c4be..a4dd935 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -175,6 +175,24 @@ pub trait FallibleIterator { Ok(None) } + /// Returns an iterator starting at the same point, but stepping by the given amount at each iteration. + /// + /// # Panics + /// + /// Panics if `step` is 0. + #[inline] + fn step_by(self, step: usize) -> StepBy + where + Self: Sized, + { + assert!(step != 0); + StepBy { + it: self, + step: step - 1, + first_take: true, + } + } + /// Returns an iterator which yields the elements of this iterator followed /// by another. #[inline] @@ -1479,6 +1497,50 @@ where } } +/// An iterator which steps through the elements of the underlying iterator by a certain amount. +#[derive(Clone, Debug)] +pub struct StepBy { + it: I, + step: usize, + first_take: bool, +} + +impl FallibleIterator for StepBy +where + I: FallibleIterator, +{ + type Item = I::Item; + type Error = I::Error; + + #[inline] + fn next(&mut self) -> Result, I::Error> { + if self.first_take { + self.first_take = false; + self.it.next() + } else { + self.it.nth(self.step) + } + } + + fn size_hint(&self) -> (usize, Option) { + let inner_hint = self.it.size_hint(); + + if self.first_take { + let f = |n| { + if n == 0 { + 0 + } else { + 1 + (n - 1) / (self.step + 1) + } + }; + (f(inner_hint.0), inner_hint.1.map(f)) + } else { + let f = |n| n / (self.step + 1); + (f(inner_hint.0), inner_hint.1.map(f)) + } + } +} + /// An iterator which yields a limited number of elements from the underlying /// iterator. #[derive(Clone, Debug)] diff --git a/src/test.rs b/src/test.rs index d8f5df0..3e5d3b3 100644 --- a/src/test.rs +++ b/src/test.rs @@ -256,6 +256,12 @@ fn position() { assert_eq!(it.clone().position(|n| if n == 3 { Err(42) } else { Ok(n == 4) }), Err(42)); } +#[test] +fn step_by() { + let it = convert(vec![0, 1, 2, 3, 4, 5, 6, 7, 8].into_iter().map(Ok::)).step_by(3); + assert_eq!(it.collect::>(), Ok(vec![0, 3, 6])); +} + #[test] fn take() { let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)).take(2); From d872bd129dc6bba45fb3810d5d895331d021ddaa Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 20 Sep 2018 22:25:38 -0700 Subject: [PATCH 12/34] Add for_each Closes #2 --- src/lib.rs | 14 ++++- src/test.rs | 173 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 130 insertions(+), 57 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a4dd935..aaebd08 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -176,9 +176,9 @@ pub trait FallibleIterator { } /// Returns an iterator starting at the same point, but stepping by the given amount at each iteration. - /// + /// /// # Panics - /// + /// /// Panics if `step` is 0. #[inline] fn step_by(self, step: usize) -> StepBy @@ -230,6 +230,16 @@ pub trait FallibleIterator { Map { it: self, f: f } } + /// Calls a fallible closure on each element of an iterator. + #[inline] + fn for_each(self, mut f: F) -> Result<(), Self::Error> + where + Self: Sized, + F: FnMut(Self::Item) -> Result<(), Self::Error>, + { + self.fold((), move |(), item| f(item)) + } + /// Returns an iterator which uses a predicate to determine which values /// should be yielded. The predicate may fail; such failures are passed to /// the caller. diff --git a/src/test.rs b/src/test.rs index 3e5d3b3..a768568 100644 --- a/src/test.rs +++ b/src/test.rs @@ -4,16 +4,40 @@ use super::{convert, FallibleIterator, Vec}; #[test] fn all() { - assert!(convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)).all(|&i| Ok(i < 4)).unwrap()); - assert!(!convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)).all(|&i| Ok(i < 4)).unwrap()); - assert!(convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)).all(|_| Err(())).is_err()); + assert!( + convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)) + .all(|&i| Ok(i < 4)) + .unwrap() + ); + assert!( + !convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)) + .all(|&i| Ok(i < 4)) + .unwrap() + ); + assert!( + convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)) + .all(|_| Err(())) + .is_err() + ); } #[test] fn any() { - assert!(convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)).any(|&i| Ok(i == 3)).unwrap()); - assert!(!convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)).any(|&i| Ok(i == 3)).unwrap()); - assert!(convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)).any(|_| Err(())).is_err()); + assert!( + convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)) + .any(|&i| Ok(i == 3)) + .unwrap() + ); + assert!( + !convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)) + .any(|&i| Ok(i == 3)) + .unwrap() + ); + assert!( + convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)) + .any(|_| Err(())) + .is_err() + ); } #[test] @@ -33,7 +57,12 @@ fn chain() { #[test] fn count() { - assert_eq!(convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)).count().unwrap(), 4); + assert_eq!( + convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)) + .count() + .unwrap(), + 4 + ); let it = Some(Ok(1)).into_iter().chain(iter::repeat(Err(()))); assert!(convert(it).count().is_err()); @@ -43,31 +72,22 @@ fn count() { fn enumerate() { let it = convert(vec![5, 6, 7, 8].into_iter().map(Ok::)).enumerate(); - assert_eq!(it.collect::>().unwrap(), [(0, 5), (1, 6), (2, 7), (3, 8)]); + assert_eq!( + it.collect::>().unwrap(), + [(0, 5), (1, 6), (2, 7), (3, 8)] + ); } #[test] fn filter() { let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); - let it = it.filter(|&x| { - if x % 2 == 0 { - Ok(x % 3 == 0) - } else { - Err(x) - } - }); + let it = it.filter(|&x| if x % 2 == 0 { Ok(x % 3 == 0) } else { Err(x) }); assert_eq!(it.clone().collect::>(), Err(1)); assert_eq!(it.rev().collect::>(), Err(3)); let it = convert(vec![0, 2, 4, 6].into_iter().map(Ok::)); - let it = it.filter(|&x| { - if x % 2 == 0 { - Ok(x % 3 == 0) - } else { - Err(x) - } - }); + let it = it.filter(|&x| if x % 2 == 0 { Ok(x % 3 == 0) } else { Err(x) }); assert_eq!(it.clone().collect::>(), Ok(vec![0, 6])); assert_eq!(it.rev().collect::>(), Ok(vec![6, 0])) @@ -91,8 +111,8 @@ fn filter_map() { assert_eq!(it.clone().collect::>(), Err(1)); assert_eq!(it.rev().collect::>(), Err(5)); - let it = convert(vec![0, 2, 3, 4, 6].into_iter().map(Ok::)) - .filter_map(twos_and_threes); + let it = + convert(vec![0, 2, 3, 4, 6].into_iter().map(Ok::)).filter_map(twos_and_threes); assert_eq!(it.clone().collect::>(), Ok(vec![10, 12, 14, 16])); assert_eq!(it.rev().collect::>(), Ok(vec![16, 14, 12, 10])); @@ -106,10 +126,26 @@ fn find() { assert_eq!(it.next(), Ok(Some(2))); let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); - assert_eq!(it.clone().find(|&x| if x == 2 { Err(29) } else { Ok(false) }), Err(29)); - assert_eq!(it.clone().find(|&x| if x == 2 { Err(29) } else { Ok(true) }), Ok(Some(0))); - assert_eq!(it.clone().rev().find(|&x| if x == 2 { Err(29) } else { Ok(false) }), Err(29)); - assert_eq!(it.rev().find(|&x| if x == 2 { Err(29) } else { Ok(true) }), Ok(Some(3))); + assert_eq!( + it.clone() + .find(|&x| if x == 2 { Err(29) } else { Ok(false) }), + Err(29) + ); + assert_eq!( + it.clone() + .find(|&x| if x == 2 { Err(29) } else { Ok(true) }), + Ok(Some(0)) + ); + assert_eq!( + it.clone() + .rev() + .find(|&x| if x == 2 { Err(29) } else { Ok(false) }), + Err(29) + ); + assert_eq!( + it.rev().find(|&x| if x == 2 { Err(29) } else { Ok(true) }), + Ok(Some(3)) + ); } #[test] @@ -129,15 +165,25 @@ fn fold() { assert_eq!(it.fold(0, add_smol), Ok(4)); } +#[test] +fn for_each() { + let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); + + let mut acc = vec![]; + it.for_each(|n| { + acc.push(n); + Ok(()) + }).unwrap(); + assert_eq!(acc, vec![0, 1, 2, 3]); +} + #[test] fn iterator() { - let it = convert("ab cd".chars().map(|c| { - if c.is_whitespace() { - Err(()) - } else { - Ok(c) - } - })); + let it = convert( + "ab cd" + .chars() + .map(|c| if c.is_whitespace() { Err(()) } else { Ok(c) }), + ); assert!(it.clone().count().is_err()); assert!(it.clone().rev().count().is_err()); @@ -157,14 +203,13 @@ fn map() { assert_eq!(it.clone().collect::>().unwrap(), [0, 2, 4, 6, 8]); assert_eq!(it.rev().collect::>().unwrap(), [8, 6, 4, 2, 0]); - let it = convert(vec![0, 1, 2, 3, 4].into_iter().map(Ok::)) - .map(|n| { - if n == 2 { - Err(()) - } else { - Ok(n * 2) - } - }); + let it = convert(vec![0, 1, 2, 3, 4].into_iter().map(Ok::)).map(|n| { + if n == 2 { + Err(()) + } else { + Ok(n * 2) + } + }); { let mut it = it.clone(); @@ -183,13 +228,11 @@ fn map() { #[test] fn map_err() { - let it = convert(vec![0, 1, 2, 3].into_iter().map(|n| { - if n % 2 == 0 { - Ok(n) - } else { - Err(n) - } - })); + let it = convert( + vec![0, 1, 2, 3] + .into_iter() + .map(|n| if n % 2 == 0 { Ok(n) } else { Err(n) }), + ); assert_eq!(it.clone().collect::>(), Err(1)); assert_eq!(it.rev().collect::>(), Err(3)); @@ -207,7 +250,11 @@ fn max_by_key() { assert_eq!(it.clone().max_by_key(|&i| Ok(-i)), Ok(Some(-10))); // Exercise failure both on the first item, and later. assert_eq!(it.clone().max_by_key(|&i| Err::(i)), Err(0)); - assert_eq!(it.clone().max_by_key(|&i| if i > 0 { Err(i) } else { Ok(-i) }), Err(3)); + assert_eq!( + it.clone() + .max_by_key(|&i| if i > 0 { Err(i) } else { Ok(-i) }), + Err(3) + ); } #[test] @@ -222,7 +269,11 @@ fn min_by_key() { assert_eq!(it.clone().min_by_key(|&i| Ok(-i)), Ok(Some(3))); // Exercise failure both on the first item, and later. assert_eq!(it.clone().min_by_key(|&i| Err::(i)), Err(0)); - assert_eq!(it.clone().min_by_key(|&i| if i > 0 { Err(i) } else { Ok(-i) }), Err(3)); + assert_eq!( + it.clone() + .min_by_key(|&i| if i > 0 { Err(i) } else { Ok(-i) }), + Err(3) + ); } #[test] @@ -252,13 +303,25 @@ fn position() { assert_eq!(it.position(|n| Ok(n == 5)).unwrap(), None); let it = convert(vec![1, 2, 3, 4].into_iter().map(Ok::)); - assert_eq!(it.clone().position(|n| if n == 3 { Err(42) } else { Ok(n == 2) }), Ok(Some(1))); - assert_eq!(it.clone().position(|n| if n == 3 { Err(42) } else { Ok(n == 4) }), Err(42)); + assert_eq!( + it.clone() + .position(|n| if n == 3 { Err(42) } else { Ok(n == 2) }), + Ok(Some(1)) + ); + assert_eq!( + it.clone() + .position(|n| if n == 3 { Err(42) } else { Ok(n == 4) }), + Err(42) + ); } #[test] fn step_by() { - let it = convert(vec![0, 1, 2, 3, 4, 5, 6, 7, 8].into_iter().map(Ok::)).step_by(3); + let it = convert( + vec![0, 1, 2, 3, 4, 5, 6, 7, 8] + .into_iter() + .map(Ok::), + ).step_by(3); assert_eq!(it.collect::>(), Ok(vec![0, 3, 6])); } From ffd8ce7ea0b6c1f79b6cfeb757312b7473e3a990 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 21 Sep 2018 21:17:43 -0700 Subject: [PATCH 13/34] Add skip_while --- src/lib.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/test.rs | 8 ++++++++ 2 files changed, 63 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index aaebd08..97751da 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -286,6 +286,20 @@ pub trait FallibleIterator { } } + /// Returns an iterator that skips elements based on a predicate. + #[inline] + fn skip_while

(self, predicate: P) -> SkipWhile + where + Self: Sized, + P: FnMut(&Self::Item) -> Result + { + SkipWhile { + it: self, + flag: false, + predicate, + } + } + /// Returns an iterator that yields only the first `n` values of this /// iterator. #[inline] @@ -1507,6 +1521,47 @@ where } } +/// An iterator which skips initial elements based on a predicate. +#[derive(Clone, Debug)] +pub struct SkipWhile { + it: I, + flag: bool, + predicate: P, +} + +impl FallibleIterator for SkipWhile +where + I: FallibleIterator, + P: FnMut(&I::Item) -> Result +{ + type Item = I::Item; + type Error = I::Error; + + #[inline] + fn next(&mut self) -> Result, I::Error> { + let flag = &mut self.flag; + let pred = &mut self.predicate; + self.it.find(move |x| { + if *flag || !pred(x)? { + *flag = true; + Ok(true) + } else { + Ok(false) + } + }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let hint = self.it.size_hint(); + if self.flag { + hint + } else { + (0, hint.1) + } + } +} + /// An iterator which steps through the elements of the underlying iterator by a certain amount. #[derive(Clone, Debug)] pub struct StepBy { diff --git a/src/test.rs b/src/test.rs index a768568..7b02b1c 100644 --- a/src/test.rs +++ b/src/test.rs @@ -315,6 +315,14 @@ fn position() { ); } +#[test] +fn skip_while() { + let it = convert(vec![1, 2, 3, 4, 1].into_iter().map(Ok::)); + assert_eq!(it.clone().skip_while(|x| Ok(*x < 1)).collect::>(), Ok(vec![1, 2, 3, 4, 1])); + assert_eq!(it.clone().skip_while(|x| Ok(*x < 3)).collect::>(), Ok(vec![3, 4, 1])); + assert_eq!(it.clone().skip_while(|x| Ok(*x < 5)).collect::>(), Ok(vec![])); +} + #[test] fn step_by() { let it = convert( From d2c5949eb650941cbbe11539845b8595c301f72a Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 21 Sep 2018 21:30:37 -0700 Subject: [PATCH 14/34] Add take_while --- src/lib.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++-- src/test.rs | 8 +++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 97751da..060a962 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -291,7 +291,7 @@ pub trait FallibleIterator { fn skip_while

(self, predicate: P) -> SkipWhile where Self: Sized, - P: FnMut(&Self::Item) -> Result + P: FnMut(&Self::Item) -> Result, { SkipWhile { it: self, @@ -300,6 +300,20 @@ pub trait FallibleIterator { } } + /// Returns an iterator that yields elements based on a predicate. + #[inline] + fn take_while

(self, predicate: P) -> TakeWhile + where + Self: Sized, + P: FnMut(&Self::Item) -> Result, + { + TakeWhile { + it: self, + flag: false, + predicate, + } + } + /// Returns an iterator that yields only the first `n` values of this /// iterator. #[inline] @@ -1532,7 +1546,7 @@ pub struct SkipWhile { impl FallibleIterator for SkipWhile where I: FallibleIterator, - P: FnMut(&I::Item) -> Result + P: FnMut(&I::Item) -> Result, { type Item = I::Item; type Error = I::Error; @@ -1644,6 +1658,52 @@ where } } +/// An iterator which yields elements based on a predicate. +#[derive(Clone, Debug)] +pub struct TakeWhile { + it: I, + flag: bool, + predicate: P, +} + +impl FallibleIterator for TakeWhile +where + I: FallibleIterator, + P: FnMut(&I::Item) -> Result, +{ + type Item = I::Item; + type Error = I::Error; + + #[inline] + fn next(&mut self) -> Result, I::Error> { + if self.flag { + Ok(None) + } else { + match self.it.next()? { + Some(item) => { + if (self.predicate)(&item)? { + Ok(Some(item)) + } else { + self.flag = true; + Ok(None) + } + } + None => Ok(None), + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.flag { + (0, Some(0)) + } else { + let hint = self.it.size_hint(); + (0, hint.1) + } + } +} + /// An iterator that yields pairs of this iterator's and another iterator's /// values. #[derive(Clone, Debug)] diff --git a/src/test.rs b/src/test.rs index 7b02b1c..a0504d9 100644 --- a/src/test.rs +++ b/src/test.rs @@ -338,3 +338,11 @@ fn take() { let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)).take(2); assert_eq!(it.collect::>().unwrap(), [0, 1]); } + +#[test] +fn take_while() { + let it = convert(vec![0, 1, 2, 3, 0].into_iter().map(Ok::)); + assert_eq!(it.clone().take_while(|x| Ok(*x < 0)).collect::>(), Ok(vec![])); + assert_eq!(it.clone().take_while(|x| Ok(*x < 2)).collect::>(), Ok(vec![0, 1])); + assert_eq!(it.clone().take_while(|x| Ok(*x < 4)).collect::>(), Ok(vec![0, 1, 2, 3, 0])); +} From 8595b46736e5579758a50dc3c54e7e45a7da2b65 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 22 Sep 2018 08:09:27 -0700 Subject: [PATCH 15/34] Add skip --- src/lib.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/test.rs | 8 ++++++++ 2 files changed, 53 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 060a962..5756e80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -314,6 +314,15 @@ pub trait FallibleIterator { } } + /// Returns an iterator which skips the first `n` values of this iterator. + #[inline] + fn skip(self, n: usize) -> Skip + where + Self: Sized, + { + Skip { it: self, n } + } + /// Returns an iterator that yields only the first `n` values of this /// iterator. #[inline] @@ -1535,6 +1544,42 @@ where } } +/// An iterator which skips initial elements. +#[derive(Clone, Debug)] +pub struct Skip { + it: I, + n: usize, +} + +impl FallibleIterator for Skip +where + I: FallibleIterator, +{ + type Item = I::Item; + type Error = I::Error; + + #[inline] + fn next(&mut self) -> Result, I::Error> { + if self.n == 0 { + self.it.next() + } else { + let n = self.n; + self.n = 0; + self.it.nth(n) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let hint = self.it.size_hint(); + + ( + hint.0.saturating_sub(self.n), + hint.1.map(|x| x.saturating_sub(self.n)), + ) + } +} + /// An iterator which skips initial elements based on a predicate. #[derive(Clone, Debug)] pub struct SkipWhile { diff --git a/src/test.rs b/src/test.rs index a0504d9..3fcdfd4 100644 --- a/src/test.rs +++ b/src/test.rs @@ -315,6 +315,14 @@ fn position() { ); } +#[test] +fn skip() { + let it = convert(vec![1, 2, 3, 4].into_iter().map(Ok::)); + assert_eq!(it.clone().skip(0).collect::>(), Ok(vec![1, 2, 3, 4])); + assert_eq!(it.clone().skip(2).collect::>(), Ok(vec![3, 4])); + assert_eq!(it.clone().skip(4).collect::>(), Ok(vec![])); +} + #[test] fn skip_while() { let it = convert(vec![1, 2, 3, 4, 1].into_iter().map(Ok::)); From b4742af2be662a0394e2a0cc67c757b4b27144f4 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 22 Sep 2018 19:59:05 -0700 Subject: [PATCH 16/34] Add scan --- src/lib.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/test.rs | 43 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 83 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5756e80..f404a25 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -336,6 +336,21 @@ pub trait FallibleIterator { } } + /// Returns an iterator which applies a stateful map to values of this + /// iterator. + #[inline] + fn scan(self, initial_state: St, f: F) -> Scan + where + Self: Sized, + F: FnMut(&mut St, Self::Item) -> Result, Self::Error>, + { + Scan { + it: self, + f, + state: initial_state, + } + } + /// Returns an iterator which yields this iterator's elements and ends after /// the first `Ok(None)`. /// @@ -1544,6 +1559,37 @@ where } } +/// An iterator which applies a stateful closure. +#[derive(Clone, Debug)] +pub struct Scan { + it: I, + f: F, + state: St, +} + +impl FallibleIterator for Scan +where + I: FallibleIterator, + F: FnMut(&mut St, I::Item) -> Result, I::Error>, +{ + type Item = B; + type Error = I::Error; + + #[inline] + fn next(&mut self) -> Result, I::Error> { + match self.it.next()? { + Some(v) => (self.f)(&mut self.state, v), + None => Ok(None), + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let hint = self.it.size_hint(); + (0, hint.1) + } +} + /// An iterator which skips initial elements. #[derive(Clone, Debug)] pub struct Skip { diff --git a/src/test.rs b/src/test.rs index 3fcdfd4..99b8307 100644 --- a/src/test.rs +++ b/src/test.rs @@ -315,6 +315,19 @@ fn position() { ); } +#[test] +fn scan() { + let it = convert(vec![1, 2, 3, 4].into_iter().map(Ok::)).scan(0, |st, v| { + if v > 3 { + Ok(None) + } else { + *st += v; + Ok(Some(-*st)) + } + }); + assert_eq!(it.collect::>(), Ok(vec![-1, -3, -6])); +} + #[test] fn skip() { let it = convert(vec![1, 2, 3, 4].into_iter().map(Ok::)); @@ -326,9 +339,18 @@ fn skip() { #[test] fn skip_while() { let it = convert(vec![1, 2, 3, 4, 1].into_iter().map(Ok::)); - assert_eq!(it.clone().skip_while(|x| Ok(*x < 1)).collect::>(), Ok(vec![1, 2, 3, 4, 1])); - assert_eq!(it.clone().skip_while(|x| Ok(*x < 3)).collect::>(), Ok(vec![3, 4, 1])); - assert_eq!(it.clone().skip_while(|x| Ok(*x < 5)).collect::>(), Ok(vec![])); + assert_eq!( + it.clone().skip_while(|x| Ok(*x < 1)).collect::>(), + Ok(vec![1, 2, 3, 4, 1]) + ); + assert_eq!( + it.clone().skip_while(|x| Ok(*x < 3)).collect::>(), + Ok(vec![3, 4, 1]) + ); + assert_eq!( + it.clone().skip_while(|x| Ok(*x < 5)).collect::>(), + Ok(vec![]) + ); } #[test] @@ -350,7 +372,16 @@ fn take() { #[test] fn take_while() { let it = convert(vec![0, 1, 2, 3, 0].into_iter().map(Ok::)); - assert_eq!(it.clone().take_while(|x| Ok(*x < 0)).collect::>(), Ok(vec![])); - assert_eq!(it.clone().take_while(|x| Ok(*x < 2)).collect::>(), Ok(vec![0, 1])); - assert_eq!(it.clone().take_while(|x| Ok(*x < 4)).collect::>(), Ok(vec![0, 1, 2, 3, 0])); + assert_eq!( + it.clone().take_while(|x| Ok(*x < 0)).collect::>(), + Ok(vec![]) + ); + assert_eq!( + it.clone().take_while(|x| Ok(*x < 2)).collect::>(), + Ok(vec![0, 1]) + ); + assert_eq!( + it.clone().take_while(|x| Ok(*x < 4)).collect::>(), + Ok(vec![0, 1, 2, 3, 0]) + ); } From 6c8ad9f48b56ec5b41af7fabbdd60a5a600df0ac Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 9 Dec 2018 21:11:18 -0800 Subject: [PATCH 17/34] Make FromFallibleIterator impls generic over hash --- src/lib.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f404a25..6240756 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,7 +90,7 @@ extern crate std; #[cfg(feature = "std")] mod imports { pub use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; - pub use std::hash::Hash; + pub use std::hash::{Hash, BuildHasher}; pub use std::prelude::v1::*; } @@ -886,17 +886,19 @@ impl FromFallibleIterator for Vec { } #[cfg(feature = "std")] -impl FromFallibleIterator for HashSet +impl FromFallibleIterator for HashSet where T: Hash + Eq, + S: BuildHasher + Default, { #[inline] - fn from_fallible_iterator(it: I) -> Result, I::Error> + fn from_fallible_iterator(it: I) -> Result, I::Error> where I: IntoFallibleIterator, { let mut it = it.into_fallible_iterator(); - let mut set = HashSet::with_capacity(it.size_hint().0); + let mut set = HashSet::default(); + set.reserve(it.size_hint().0); while let Some(v) = it.next()? { set.insert(v); } @@ -905,17 +907,19 @@ where } #[cfg(feature = "std")] -impl FromFallibleIterator<(K, V)> for HashMap +impl FromFallibleIterator<(K, V)> for HashMap where K: Hash + Eq, + S: BuildHasher + Default, { #[inline] - fn from_fallible_iterator(it: I) -> Result, I::Error> + fn from_fallible_iterator(it: I) -> Result, I::Error> where I: IntoFallibleIterator, { let mut it = it.into_fallible_iterator(); - let mut map = HashMap::with_capacity(it.size_hint().0); + let mut map = HashMap::default(); + map.reserve(it.size_hint().0); while let Some((k, v)) = it.next()? { map.insert(k, v); } From 4886826a75cdf1fcf29597565bcdaa0bbf6adb35 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 15:31:48 -0800 Subject: [PATCH 18/34] Add flat_map --- src/lib.rs | 51 ++++++++++++++++++++++++++++++++++++++- src/test.rs | 69 ++++++++++++++++++++++++++++------------------------- 2 files changed, 87 insertions(+), 33 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6240756..dacaa70 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,7 +90,7 @@ extern crate std; #[cfg(feature = "std")] mod imports { pub use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; - pub use std::hash::{Hash, BuildHasher}; + pub use std::hash::{BuildHasher, Hash}; pub use std::prelude::v1::*; } @@ -351,6 +351,20 @@ pub trait FallibleIterator { } } + /// Returns an iterator which maps this iterator's elements to iterators, yielding those iterators' values. + #[inline] + fn flat_map(self, f: F) -> FlatMap + where + Self: Sized, + U: IntoFallibleIterator, + F: FnMut(Self::Item) -> Result, + { + FlatMap { + it: self.map(f), + cur: None, + } + } + /// Returns an iterator which yields this iterator's elements and ends after /// the first `Ok(None)`. /// @@ -1348,6 +1362,41 @@ where } } +/// An iterator which maps each element to another iterator, yielding that iterator's elements. +#[derive(Clone)] +pub struct FlatMap +where + U: IntoFallibleIterator, +{ + it: Map, + cur: Option, +} + +impl FallibleIterator for FlatMap +where + I: FallibleIterator, + U: IntoFallibleIterator, + F: FnMut(I::Item) -> Result, +{ + type Item = U::Item; + type Error = U::Error; + + #[inline] + fn next(&mut self) -> Result, U::Error> { + loop { + if let Some(it) = &mut self.cur { + if let Some(v) = it.next()? { + return Ok(Some(v)); + } + } + match self.it.next()? { + Some(it) => self.cur = Some(it.into_fallible_iterator()), + None => return Ok(None), + } + } + } +} + /// An iterator that yields `Ok(None)` forever after the underlying iterator /// yields `Ok(None)` once. #[derive(Clone, Debug)] diff --git a/src/test.rs b/src/test.rs index 99b8307..f0fb59a 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,43 +1,32 @@ use core::iter; +use core::ops::Range; use super::{convert, FallibleIterator, Vec}; #[test] fn all() { - assert!( - convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)) - .all(|&i| Ok(i < 4)) - .unwrap() - ); - assert!( - !convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)) - .all(|&i| Ok(i < 4)) - .unwrap() - ); - assert!( - convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)) - .all(|_| Err(())) - .is_err() - ); + assert!(convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)) + .all(|&i| Ok(i < 4)) + .unwrap()); + assert!(!convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)) + .all(|&i| Ok(i < 4)) + .unwrap()); + assert!(convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)) + .all(|_| Err(())) + .is_err()); } #[test] fn any() { - assert!( - convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)) - .any(|&i| Ok(i == 3)) - .unwrap() - ); - assert!( - !convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)) - .any(|&i| Ok(i == 3)) - .unwrap() - ); - assert!( - convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)) - .any(|_| Err(())) - .is_err() - ); + assert!(convert([0, 1, 2, 3].iter().map(Ok::<&u32, ()>)) + .any(|&i| Ok(i == 3)) + .unwrap()); + assert!(!convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)) + .any(|&i| Ok(i == 3)) + .unwrap()); + assert!(convert([0, 1, 2, 4].iter().map(Ok::<&u32, ()>)) + .any(|_| Err(())) + .is_err()); } #[test] @@ -173,7 +162,8 @@ fn for_each() { it.for_each(|n| { acc.push(n); Ok(()) - }).unwrap(); + }) + .unwrap(); assert_eq!(acc, vec![0, 1, 2, 3]); } @@ -359,7 +349,8 @@ fn step_by() { vec![0, 1, 2, 3, 4, 5, 6, 7, 8] .into_iter() .map(Ok::), - ).step_by(3); + ) + .step_by(3); assert_eq!(it.collect::>(), Ok(vec![0, 3, 6])); } @@ -385,3 +376,17 @@ fn take_while() { Ok(vec![0, 1, 2, 3, 0]) ); } + +#[test] +fn flat_map() { + let it = convert( + vec![0..1, 0..0, 1..5] + .into_iter() + .map(Ok::, ()>), + ) + .flat_map(|r| Ok(convert(r.map(Ok::)))); + assert_eq!( + it.collect::>(), + Ok(vec![0, 1, 2, 3, 4]) + ) +} From 8f49be9c6ae6b83c2f8369b4bf1bc82e2356e357 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 15:42:21 -0800 Subject: [PATCH 19/34] Implement flatten --- src/lib.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++-- src/test.rs | 17 +++++++++----- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index dacaa70..0efd4ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -365,6 +365,19 @@ pub trait FallibleIterator { } } + /// Returns an iterator which flattens an iterator of iterators, yielding those iterators' values. + #[inline] + fn flatten(self) -> Flatten + where + Self: Sized, + Self::Item: IntoFallibleIterator, + { + Flatten { + it: self, + cur: None, + } + } + /// Returns an iterator which yields this iterator's elements and ends after /// the first `Ok(None)`. /// @@ -1362,8 +1375,8 @@ where } } -/// An iterator which maps each element to another iterator, yielding that iterator's elements. -#[derive(Clone)] +/// An iterator which maps each element to another iterator, yielding those iterator's elements. +#[derive(Clone, Debug)] pub struct FlatMap where U: IntoFallibleIterator, @@ -1397,6 +1410,55 @@ where } } +/// An iterator which flattens an iterator of iterators, yielding those iterators' elements. +pub struct Flatten +where + I: FallibleIterator, + I::Item: IntoFallibleIterator, +{ + it: I, + cur: Option<::IntoIter>, +} + +impl Clone for Flatten +where + I: FallibleIterator + Clone, + I::Item: IntoFallibleIterator, + ::IntoIter: Clone, +{ + #[inline] + fn clone(&self) -> Flatten { + Flatten { + it: self.it.clone(), + cur: self.cur.clone(), + } + } +} + +impl FallibleIterator for Flatten +where + I: FallibleIterator, + I::Item: IntoFallibleIterator, +{ + type Item = ::Item; + type Error = ::Error; + + #[inline] + fn next(&mut self) -> Result, Self::Error> { + loop { + if let Some(it) = &mut self.cur { + if let Some(v) = it.next()? { + return Ok(Some(v)); + } + } + match self.it.next()? { + Some(it) => self.cur = Some(it.into_fallible_iterator()), + None => return Ok(None), + } + } + } +} + /// An iterator that yields `Ok(None)` forever after the underlying iterator /// yields `Ok(None)` once. #[derive(Clone, Debug)] diff --git a/src/test.rs b/src/test.rs index f0fb59a..bcd6ed2 100644 --- a/src/test.rs +++ b/src/test.rs @@ -379,14 +379,19 @@ fn take_while() { #[test] fn flat_map() { + let it = convert(vec![0..1, 0..0, 1..5].into_iter().map(Ok::, ()>)) + .flat_map(|r| Ok(convert(r.map(Ok::)))); + assert_eq!(it.collect::>(), Ok(vec![0, 1, 2, 3, 4])); +} + +#[test] +fn flatten() { let it = convert( vec![0..1, 0..0, 1..5] .into_iter() - .map(Ok::, ()>), - ) - .flat_map(|r| Ok(convert(r.map(Ok::)))); - assert_eq!( - it.collect::>(), - Ok(vec![0, 1, 2, 3, 4]) + .map(|r| convert(r.map(Ok::))) + .map(Ok::<_, ()>), ) + .flatten(); + assert_eq!(it.collect::>(), Ok(vec![0, 1, 2, 3, 4])); } From 8657fd1499efcae1df76029bb9da300e4fcba7d3 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 15:51:32 -0800 Subject: [PATCH 20/34] Migrate to 2018 edition --- .circleci/config.yml | 2 +- Cargo.toml | 1 + src/lib.rs | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1834f91..cf9d2e4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,7 +22,7 @@ version: 2 jobs: stable: docker: - - image: rust:1.26.0 + - image: rust:1.33.0 environment: RUSTFLAGS: -D warnings working_directory: ~/build diff --git a/Cargo.toml b/Cargo.toml index 0deccfa..e8fd7e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "fallible-iterator" version = "0.2.0" authors = ["Steven Fackler "] +edition = "2018" license = "MIT/Apache-2.0" description = "Fallible iterator traits" repository = "https://github.com/sfackler/rust-fallible-iterator" diff --git a/src/lib.rs b/src/lib.rs index 0efd4ad..004f7cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -95,7 +95,7 @@ mod imports { } #[cfg(any(feature = "std", feature = "alloc"))] -use imports::*; +use crate::imports::*; #[cfg(any(feature = "std", feature = "alloc"))] #[cfg(test)] @@ -1949,4 +1949,4 @@ where } } -fn _is_object_safe(_: &FallibleIterator) {} +fn _is_object_safe(_: &dyn FallibleIterator) {} From fa8dc7da5468a474b64671cd8bf6f695748aff5c Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 15:50:51 -0800 Subject: [PATCH 21/34] Implement inspect --- src/lib.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/test.rs | 8 ++++++++ 2 files changed, 67 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 004f7cb..da1334c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -378,6 +378,16 @@ pub trait FallibleIterator { } } + /// Returns an iterator which passes each element to a closure before returning it. + #[inline] + fn inspect(self, f: F) -> Inspect + where + Self: Sized, + F: FnMut(&Self::Item) -> Result<(), Self::Error>, + { + Inspect { it: self, f } + } + /// Returns an iterator which yields this iterator's elements and ends after /// the first `Ok(None)`. /// @@ -1505,6 +1515,55 @@ where } } +/// An iterator which passes each element to a closure before returning it. +#[derive(Clone, Debug)] +pub struct Inspect { + it: I, + f: F, +} + +impl FallibleIterator for Inspect +where + I: FallibleIterator, + F: FnMut(&I::Item) -> Result<(), I::Error>, +{ + type Item = I::Item; + type Error = I::Error; + + #[inline] + fn next(&mut self) -> Result, I::Error> { + match self.it.next()? { + Some(i) => { + (self.f)(&i)?; + Ok(Some(i)) + } + None => Ok(None), + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } +} + +impl DoubleEndedFallibleIterator for Inspect +where + I: DoubleEndedFallibleIterator, + F: FnMut(&I::Item) -> Result<(), I::Error>, +{ + #[inline] + fn next_back(&mut self) -> Result, I::Error> { + match self.it.next_back()? { + Some(i) => { + (self.f)(&i)?; + Ok(Some(i)) + } + None => Ok(None), + } + } +} + /// A normal (non-fallible) iterator which wraps a fallible iterator. #[derive(Clone, Debug)] pub struct Iterator(I); diff --git a/src/test.rs b/src/test.rs index bcd6ed2..1682e66 100644 --- a/src/test.rs +++ b/src/test.rs @@ -395,3 +395,11 @@ fn flatten() { .flatten(); assert_eq!(it.collect::>(), Ok(vec![0, 1, 2, 3, 4])); } + +#[test] +fn inspect() { + let mut buf = vec![]; + let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)).inspect(|v| Ok(buf.push(*v))); + it.count().unwrap(); + assert_eq!(buf, vec![0, 1, 2, 3]); +} From 627803dcba005c76cb12d5030dbf36284e25d2c5 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 16:00:39 -0800 Subject: [PATCH 22/34] Implement partition --- src/lib.rs | 43 +++++++++++++++++++++++++++++++++---------- src/test.rs | 8 ++++++++ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index da1334c..0e71918 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -378,16 +378,6 @@ pub trait FallibleIterator { } } - /// Returns an iterator which passes each element to a closure before returning it. - #[inline] - fn inspect(self, f: F) -> Inspect - where - Self: Sized, - F: FnMut(&Self::Item) -> Result<(), Self::Error>, - { - Inspect { it: self, f } - } - /// Returns an iterator which yields this iterator's elements and ends after /// the first `Ok(None)`. /// @@ -405,6 +395,16 @@ pub trait FallibleIterator { } } + /// Returns an iterator which passes each element to a closure before returning it. + #[inline] + fn inspect(self, f: F) -> Inspect + where + Self: Sized, + F: FnMut(&Self::Item) -> Result<(), Self::Error>, + { + Inspect { it: self, f } + } + /// Borrow an iterator rather than consuming it. /// /// This is useful to allow the use of iterator adaptors that would @@ -429,6 +429,29 @@ pub trait FallibleIterator { T::from_fallible_iterator(self) } + /// Transforms the iterator into two collections, partitioning elements by a closure. + #[inline] + fn partition(self, mut f: F) -> Result<(B, B), Self::Error> + where + Self: Sized, + B: Default + Extend, + F: FnMut(&Self::Item) -> Result, + { + let mut a = B::default(); + let mut b = B::default(); + + self.for_each(|i| { + if f(&i)? { + a.extend(Some(i)); + } else { + b.extend(Some(i)); + } + Ok(()) + })?; + + Ok((a, b)) + } + /// Applies a function over the elements of the iterator, producing a single /// final value. The function may fail; such failures are returned to the /// caller. diff --git a/src/test.rs b/src/test.rs index 1682e66..4d308e9 100644 --- a/src/test.rs +++ b/src/test.rs @@ -403,3 +403,11 @@ fn inspect() { it.count().unwrap(); assert_eq!(buf, vec![0, 1, 2, 3]); } + +#[test] +fn partition() { + let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); + let (even, odd): (Vec, Vec) = it.partition(|i| Ok(*i % 2 == 0)).unwrap(); + assert_eq!(even, vec![0, 2]); + assert_eq!(odd, vec![1, 3]); +} From d58c603f67db343ee488bbaa10ac16541df07ad0 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 16:05:23 -0800 Subject: [PATCH 23/34] Add find_map --- src/lib.rs | 10 ++++++++++ src/test.rs | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 0e71918..5620241 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -519,6 +519,16 @@ pub trait FallibleIterator { Ok(None) } + /// Applies a function to the elements of the iterator, returning the first non-`None` result. + #[inline] + fn find_map(&mut self, f: F) -> Result, Self::Error> + where + Self: Sized, + F: FnMut(Self::Item) -> Result, Self::Error> + { + self.filter_map(f).next() + } + /// Returns the position of the first element of this iterator that matches /// a predicate. The predicate may fail; such failures are returned to the /// caller. diff --git a/src/test.rs b/src/test.rs index 4d308e9..17c539a 100644 --- a/src/test.rs +++ b/src/test.rs @@ -411,3 +411,15 @@ fn partition() { assert_eq!(even, vec![0, 2]); assert_eq!(odd, vec![1, 3]); } + +#[test] +fn find_map() { + let mut it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); + assert_eq!( + it.find_map(|v| match v { + 2 => Ok(Some("hi")), + _ => Ok(None), + }), + Ok(Some("hi")) + ); +} From 60acd0aafc3544379b475c5952ad562d2d88e4f6 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 16:22:17 -0800 Subject: [PATCH 24/34] Implement max_by --- src/lib.rs | 57 ++++++++++++++++++++++++++++++++++++----------------- src/test.rs | 6 ++++++ 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5620241..b1aedbd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -569,49 +569,70 @@ pub trait FallibleIterator { Ok(Some(max)) } - /// Returns the minimal element of the iterator. + /// Returns the element of the iterator which gives the maximum value from + /// the function. #[inline] - fn min(mut self) -> Result, Self::Error> + fn max_by_key(mut self, mut f: F) -> Result, Self::Error> where Self: Sized, - Self::Item: Ord, + B: Ord, + F: FnMut(&Self::Item) -> Result, { - let mut min = match self.next()? { - Some(v) => v, + let mut max = match self.next()? { + Some(v) => (f(&v)?, v), None => return Ok(None), }; while let Some(v) = self.next()? { - if min > v { - min = v; + let b = f(&v)?; + if max.0 < b { + max = (b, v); } } - Ok(Some(min)) + Ok(Some(max.1)) } - /// Returns the element of the iterator which gives the maximum value from - /// the function. The function may fail; such failures are returned to the caller. + /// Returns the element that gives the maximum value with respect to the function. #[inline] - fn max_by_key(mut self, mut f: F) -> Result, Self::Error> + fn max_by(mut self, mut f: F) -> Result, Self::Error> where Self: Sized, - B: Ord, - F: FnMut(&Self::Item) -> Result, + F: FnMut(&Self::Item, &Self::Item) -> Result, { let mut max = match self.next()? { - Some(v) => (f(&v)?, v), + Some(v) => v, None => return Ok(None), }; while let Some(v) = self.next()? { - let b = f(&v)?; - if max.0 < b { - max = (b, v); + if f(&max, &v)? != Ordering::Greater { + max = v; } } - Ok(Some(max.1)) + Ok(Some(max)) + } + + /// Returns the minimal element of the iterator. + #[inline] + fn min(mut self) -> Result, Self::Error> + where + Self: Sized, + Self::Item: Ord, + { + let mut min = match self.next()? { + Some(v) => v, + None => return Ok(None), + }; + + while let Some(v) = self.next()? { + if min > v { + min = v; + } + } + + Ok(Some(min)) } /// Returns the element of the iterator which gives the minimum value from diff --git a/src/test.rs b/src/test.rs index 17c539a..84f1918 100644 --- a/src/test.rs +++ b/src/test.rs @@ -247,6 +247,12 @@ fn max_by_key() { ); } +#[test] +fn max_by() { + let it = convert(vec![0, 3, 1, -10].into_iter().map(Ok::)); + assert_eq!(it.max_by(|a, b| Ok(b.cmp(a))), Ok(Some(-10))); +} + #[test] fn min() { let it = convert(vec![0, 3, -10, 1].into_iter().map(Ok::)); From 04620cd7b66148d272aab11b75fc79e3094b4542 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 16:23:36 -0800 Subject: [PATCH 25/34] Implement min_by --- src/lib.rs | 23 ++++++++++++++++++++++- src/test.rs | 6 ++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index b1aedbd..e6b07f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -636,7 +636,7 @@ pub trait FallibleIterator { } /// Returns the element of the iterator which gives the minimum value from - /// the function. The function may fail; such failures are returned to the caller. + /// the function. #[inline] fn min_by_key(mut self, mut f: F) -> Result, Self::Error> where @@ -659,6 +659,27 @@ pub trait FallibleIterator { Ok(Some(min.1)) } + /// Returns the element that gives the minimum value with respect to the function. + #[inline] + fn min_by(mut self, mut f: F) -> Result, Self::Error> + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Result, + { + let mut min= match self.next()? { + Some(v) => v, + None => return Ok(None), + }; + + while let Some(v) = self.next()? { + if f(&min, &v)? != Ordering::Less { + min = v; + } + } + + Ok(Some(min)) + } + /// Returns an iterator that yields this iterator's items in the opposite /// order. #[inline] diff --git a/src/test.rs b/src/test.rs index 84f1918..69dd0f0 100644 --- a/src/test.rs +++ b/src/test.rs @@ -272,6 +272,12 @@ fn min_by_key() { ); } +#[test] +fn min_by() { + let it = convert(vec![0, 3, 1, -10].into_iter().map(Ok::)); + assert_eq!(it.min_by(|a, b| Ok(b.cmp(a))), Ok(Some(3))); +} + #[test] fn nth() { let mut it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); From d269d1fd4d5869c6d15069ac8ee6adcfd31a35b6 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 16:27:38 -0800 Subject: [PATCH 26/34] Implement unzip --- src/lib.rs | 24 ++++++++++++++++++++++-- src/test.rs | 8 ++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e6b07f0..630b6c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -524,7 +524,7 @@ pub trait FallibleIterator { fn find_map(&mut self, f: F) -> Result, Self::Error> where Self: Sized, - F: FnMut(Self::Item) -> Result, Self::Error> + F: FnMut(Self::Item) -> Result, Self::Error>, { self.filter_map(f).next() } @@ -666,7 +666,7 @@ pub trait FallibleIterator { Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Result, { - let mut min= match self.next()? { + let mut min = match self.next()? { Some(v) => v, None => return Ok(None), }; @@ -690,6 +690,26 @@ pub trait FallibleIterator { Rev(self) } + /// Converts an iterator of pairs into a pair of containers. + #[inline] + fn unzip(self) -> Result<(FromA, FromB), Self::Error> + where + Self: Sized + FallibleIterator, + FromA: Default + Extend, + FromB: Default + Extend, + { + let mut from_a = FromA::default(); + let mut from_b = FromB::default(); + + self.for_each(|(a, b)| { + from_a.extend(Some(a)); + from_b.extend(Some(b)); + Ok(()) + })?; + + Ok((from_a, from_b)) + } + /// Returns an iterator which clones all of its elements. #[inline] fn cloned<'a, T>(self) -> Cloned diff --git a/src/test.rs b/src/test.rs index 69dd0f0..57afaba 100644 --- a/src/test.rs +++ b/src/test.rs @@ -435,3 +435,11 @@ fn find_map() { Ok(Some("hi")) ); } + +#[test] +fn unzip() { + let it = convert(vec![(0, 0), (1, -1), (2, -2), (3, -3)].into_iter().map(Ok::<_, ()>)); + let (pos, neg): (Vec, Vec) = it.unzip().unwrap(); + assert_eq!(pos, vec![0, 1, 2, 3]); + assert_eq!(neg, vec![0, -1, -2, -3]); +} From a3243e419049e525b2374ba65f0e3c4c0132c85c Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 16:33:30 -0800 Subject: [PATCH 27/34] Add cycle --- src/lib.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ src/test.rs | 12 +++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 630b6c9..dad44cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -720,6 +720,18 @@ pub trait FallibleIterator { Cloned(self) } + /// Returns an iterator which repeas this iterator endlessly. + #[inline] + fn cycle(self) -> Cycle + where + Self: Sized + Clone, + { + Cycle { + it: self.clone(), + cur: self, + } + } + /// Lexicographically compares the elements of this iterator to that of /// another. #[inline] @@ -2064,6 +2076,37 @@ where } } +/// An iterator which cycles another endlessly. +#[derive(Clone, Debug)] +pub struct Cycle { + it: I, + cur: I, +} + +impl FallibleIterator for Cycle +where + I: FallibleIterator + Clone, +{ + type Item = I::Item; + type Error = I::Error; + + #[inline] + fn next(&mut self) -> Result, I::Error> { + match self.cur.next()? { + None => { + self.cur = self.it.clone(); + self.cur.next() + } + Some(v) => Ok(Some(v)), + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (usize::max_value(), None) + } +} + /// An iterator that yields pairs of this iterator's and another iterator's /// values. #[derive(Clone, Debug)] diff --git a/src/test.rs b/src/test.rs index 57afaba..f7627c4 100644 --- a/src/test.rs +++ b/src/test.rs @@ -438,8 +438,18 @@ fn find_map() { #[test] fn unzip() { - let it = convert(vec![(0, 0), (1, -1), (2, -2), (3, -3)].into_iter().map(Ok::<_, ()>)); + let it = convert( + vec![(0, 0), (1, -1), (2, -2), (3, -3)] + .into_iter() + .map(Ok::<_, ()>), + ); let (pos, neg): (Vec, Vec) = it.unzip().unwrap(); assert_eq!(pos, vec![0, 1, 2, 3]); assert_eq!(neg, vec![0, -1, -2, -3]); } + +#[test] +fn cycle() { + let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)).cycle(); + assert_eq!(it.take(6).clone().collect::>(), Ok(vec![0, 1, 2, 3, 0, 1])); +} From e6667d96c0b9b309ef4ad3dc1b9a61a199d8bca8 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 17:17:36 -0800 Subject: [PATCH 28/34] Make IntoFallibleIterator naming consistent --- src/lib.rs | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index dad44cd..025af9c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -211,12 +211,12 @@ pub trait FallibleIterator { /// Returns an iterator that yields pairs of this iterator's and another /// iterator's values. #[inline] - fn zip(self, o: I) -> Zip + fn zip(self, o: I) -> Zip where Self: Sized, I: IntoFallibleIterator, { - Zip(self, o.into_fallible_iterator()) + Zip(self, o.into_fallible_iter()) } /// Returns an iterator which applies a fallible transform to the elements @@ -741,7 +741,7 @@ pub trait FallibleIterator { I: IntoFallibleIterator, Self::Item: Ord, { - let mut other = other.into_fallible_iterator(); + let mut other = other.into_fallible_iter(); loop { match (self.next()?, other.next()?) { @@ -765,7 +765,7 @@ pub trait FallibleIterator { I: IntoFallibleIterator, Self::Item: PartialOrd, { - let mut other = other.into_fallible_iterator(); + let mut other = other.into_fallible_iter(); loop { match (self.next()?, other.next()?) { @@ -789,7 +789,7 @@ pub trait FallibleIterator { I: IntoFallibleIterator, Self::Item: PartialEq, { - let mut other = other.into_fallible_iterator(); + let mut other = other.into_fallible_iter(); loop { match (self.next()?, other.next()?) { @@ -813,7 +813,7 @@ pub trait FallibleIterator { I: IntoFallibleIterator, Self::Item: PartialEq, { - let mut other = other.into_fallible_iterator(); + let mut other = other.into_fallible_iter(); loop { match (self.next()?, other.next()?) { @@ -837,7 +837,7 @@ pub trait FallibleIterator { I: IntoFallibleIterator, Self::Item: PartialOrd, { - let mut other = other.into_fallible_iterator(); + let mut other = other.into_fallible_iter(); loop { match (self.next()?, other.next()?) { @@ -863,7 +863,7 @@ pub trait FallibleIterator { I: IntoFallibleIterator, Self::Item: PartialOrd, { - let mut other = other.into_fallible_iterator(); + let mut other = other.into_fallible_iter(); loop { match (self.next()?, other.next()?) { @@ -889,7 +889,7 @@ pub trait FallibleIterator { I: IntoFallibleIterator, Self::Item: PartialOrd, { - let mut other = other.into_fallible_iterator(); + let mut other = other.into_fallible_iter(); loop { match (self.next()?, other.next()?) { @@ -915,7 +915,7 @@ pub trait FallibleIterator { I: IntoFallibleIterator, Self::Item: PartialOrd, { - let mut other = other.into_fallible_iterator(); + let mut other = other.into_fallible_iter(); loop { match (self.next()?, other.next()?) { @@ -1020,7 +1020,7 @@ impl FromFallibleIterator for Vec { where I: IntoFallibleIterator, { - let mut it = it.into_fallible_iterator(); + let mut it = it.into_fallible_iter(); let mut vec = Vec::with_capacity(it.size_hint().0); while let Some(v) = it.next()? { vec.push(v); @@ -1040,7 +1040,7 @@ where where I: IntoFallibleIterator, { - let mut it = it.into_fallible_iterator(); + let mut it = it.into_fallible_iter(); let mut set = HashSet::default(); set.reserve(it.size_hint().0); while let Some(v) = it.next()? { @@ -1061,7 +1061,7 @@ where where I: IntoFallibleIterator, { - let mut it = it.into_fallible_iterator(); + let mut it = it.into_fallible_iter(); let mut map = HashMap::default(); map.reserve(it.size_hint().0); while let Some((k, v)) = it.next()? { @@ -1081,7 +1081,7 @@ where where I: IntoFallibleIterator, { - let mut it = it.into_fallible_iterator(); + let mut it = it.into_fallible_iter(); let mut set = BTreeSet::new(); while let Some(v) = it.next()? { set.insert(v); @@ -1100,7 +1100,7 @@ where where I: IntoFallibleIterator, { - let mut it = it.into_fallible_iterator(); + let mut it = it.into_fallible_iter(); let mut map = BTreeMap::new(); while let Some((k, v)) = it.next()? { map.insert(k, v); @@ -1118,10 +1118,10 @@ pub trait IntoFallibleIterator { type Error; /// The iterator. - type IntoIter: FallibleIterator; + type IntoFallibleIter: FallibleIterator; /// Creates a fallible iterator from a value. - fn into_fallible_iterator(self) -> Self::IntoIter; + fn into_fallible_iter(self) -> Self::IntoFallibleIter; } impl IntoFallibleIterator for I @@ -1130,10 +1130,10 @@ where { type Item = I::Item; type Error = I::Error; - type IntoIter = I; + type IntoFallibleIter = I; #[inline] - fn into_fallible_iterator(self) -> I { + fn into_fallible_iter(self) -> I { self } } @@ -1499,7 +1499,7 @@ where U: IntoFallibleIterator, { it: Map, - cur: Option, + cur: Option, } impl FallibleIterator for FlatMap @@ -1520,7 +1520,7 @@ where } } match self.it.next()? { - Some(it) => self.cur = Some(it.into_fallible_iterator()), + Some(it) => self.cur = Some(it.into_fallible_iter()), None => return Ok(None), } } @@ -1534,14 +1534,14 @@ where I::Item: IntoFallibleIterator, { it: I, - cur: Option<::IntoIter>, + cur: Option<::IntoFallibleIter>, } impl Clone for Flatten where I: FallibleIterator + Clone, I::Item: IntoFallibleIterator, - ::IntoIter: Clone, + ::IntoFallibleIter: Clone, { #[inline] fn clone(&self) -> Flatten { @@ -1569,7 +1569,7 @@ where } } match self.it.next()? { - Some(it) => self.cur = Some(it.into_fallible_iterator()), + Some(it) => self.cur = Some(it.into_fallible_iter()), None => return Ok(None), } } From 8e17a7dd11c604ab9bbb33797693e763b2395b20 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 19:18:16 -0800 Subject: [PATCH 29/34] Elide some lifetimes --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 025af9c..8db921f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -953,7 +953,7 @@ pub trait FallibleIterator { } } -impl<'a, I: FallibleIterator + ?Sized> FallibleIterator for &'a mut I { +impl FallibleIterator for &mut I { type Item = I::Item; type Error = I::Error; @@ -968,7 +968,7 @@ impl<'a, I: FallibleIterator + ?Sized> FallibleIterator for &'a mut I { } } -impl<'a, I: DoubleEndedFallibleIterator + ?Sized> DoubleEndedFallibleIterator for &'a mut I { +impl DoubleEndedFallibleIterator for &mut I { #[inline] fn next_back(&mut self) -> Result, I::Error> { (**self).next_back() From 31fb3d45fdb60e84ab369bd83a25666ff9429ad9 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 21:22:32 -0800 Subject: [PATCH 30/34] Override implementations, use fold when possible --- src/lib.rs | 359 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 272 insertions(+), 87 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8db921f..4d8ed38 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -138,16 +138,11 @@ pub trait FallibleIterator { /// Consumes the iterator, returning the number of remaining items. #[inline] - fn count(mut self) -> Result + fn count(self) -> Result where Self: Sized, { - let mut count = 0; - while let Some(_) = self.next()? { - count += 1; - } - - Ok(count) + self.fold(0, |n, _| Ok(n + 1)) } /// Returns the last element of the iterator. @@ -453,8 +448,7 @@ pub trait FallibleIterator { } /// Applies a function over the elements of the iterator, producing a single - /// final value. The function may fail; such failures are returned to the - /// caller. + /// final value. #[inline] fn fold(mut self, mut init: B, mut f: F) -> Result where @@ -469,7 +463,6 @@ pub trait FallibleIterator { } /// Determines if all elements of this iterator match a predicate. - /// The predicate may fail; such failures are passed to the caller. #[inline] fn all(&mut self, mut f: F) -> Result where @@ -486,7 +479,6 @@ pub trait FallibleIterator { } /// Determines if any element of this iterator matches a predicate. - /// The predicate may fail; such failures are passed to the caller. #[inline] fn any(&mut self, mut f: F) -> Result where @@ -503,7 +495,6 @@ pub trait FallibleIterator { } /// Returns the first element of the iterator that matches a predicate. - /// The predicate may fail; such failures are passed along to the caller. #[inline] fn find(&mut self, mut f: F) -> Result, Self::Error> where @@ -550,23 +541,12 @@ pub trait FallibleIterator { /// Returns the maximal element of the iterator. #[inline] - fn max(mut self) -> Result, Self::Error> + fn max(self) -> Result, Self::Error> where Self: Sized, Self::Item: Ord, { - let mut max = match self.next()? { - Some(v) => v, - None => return Ok(None), - }; - - while let Some(v) = self.next()? { - if max < v { - max = v; - } - } - - Ok(Some(max)) + self.max_by(|a, b| Ok(a.cmp(b))) } /// Returns the element of the iterator which gives the maximum value from @@ -578,19 +558,20 @@ pub trait FallibleIterator { B: Ord, F: FnMut(&Self::Item) -> Result, { - let mut max = match self.next()? { + let max = match self.next()? { Some(v) => (f(&v)?, v), None => return Ok(None), }; - while let Some(v) = self.next()? { - let b = f(&v)?; - if max.0 < b { - max = (b, v); + self.fold(max, |(key, max), v| { + let new_key = f(&v)?; + if key > new_key { + Ok((key, max)) + } else { + Ok((new_key, v)) } - } - - Ok(Some(max.1)) + }) + .map(|v| Some(v.1)) } /// Returns the element that gives the maximum value with respect to the function. @@ -600,39 +581,29 @@ pub trait FallibleIterator { Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Result, { - let mut max = match self.next()? { + let max = match self.next()? { Some(v) => v, None => return Ok(None), }; - while let Some(v) = self.next()? { - if f(&max, &v)? != Ordering::Greater { - max = v; + self.fold(max, |max, v| { + if f(&max, &v)? == Ordering::Greater { + Ok(max) + } else { + Ok(v) } - } - - Ok(Some(max)) + }) + .map(Some) } /// Returns the minimal element of the iterator. #[inline] - fn min(mut self) -> Result, Self::Error> + fn min(self) -> Result, Self::Error> where Self: Sized, Self::Item: Ord, { - let mut min = match self.next()? { - Some(v) => v, - None => return Ok(None), - }; - - while let Some(v) = self.next()? { - if min > v { - min = v; - } - } - - Ok(Some(min)) + self.min_by(|a, b| Ok(a.cmp(b))) } /// Returns the element of the iterator which gives the minimum value from @@ -644,19 +615,20 @@ pub trait FallibleIterator { B: Ord, F: FnMut(&Self::Item) -> Result, { - let mut min = match self.next()? { + let min = match self.next()? { Some(v) => (f(&v)?, v), None => return Ok(None), }; - while let Some(v) = self.next()? { - let b = f(&v)?; - if min.0 > b { - min = (b, v); + self.fold(min, |(key, min), v| { + let new_key = f(&v)?; + if key < new_key { + Ok((key, min)) + } else { + Ok((new_key, v)) } - } - - Ok(Some(min.1)) + }) + .map(|v| Some(v.1)) } /// Returns the element that gives the minimum value with respect to the function. @@ -666,18 +638,19 @@ pub trait FallibleIterator { Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Result, { - let mut min = match self.next()? { + let min = match self.next()? { Some(v) => v, None => return Ok(None), }; - while let Some(v) = self.next()? { - if f(&min, &v)? != Ordering::Less { - min = v; + self.fold(min, |min, v| { + if f(&min, &v)? == Ordering::Less { + Ok(min) + } else { + Ok(v) } - } - - Ok(Some(min)) + }) + .map(Some) } /// Returns an iterator that yields this iterator's items in the opposite @@ -966,6 +939,11 @@ impl FallibleIterator for &mut I { fn size_hint(&self) -> (usize, Option) { (**self).size_hint() } + + #[inline] + fn nth(&mut self, n: usize) -> Result, I::Error> { + (**self).nth(n) + } } impl DoubleEndedFallibleIterator for &mut I { @@ -989,6 +967,11 @@ impl FallibleIterator for Box { fn size_hint(&self) -> (usize, Option) { (**self).size_hint() } + + #[inline] + fn nth(&mut self, n: usize) -> Result, I::Error> { + (**self).nth(n) + } } #[cfg(any(feature = "std", feature = "alloc"))] @@ -1020,11 +1003,9 @@ impl FromFallibleIterator for Vec { where I: IntoFallibleIterator, { - let mut it = it.into_fallible_iter(); + let it = it.into_fallible_iter(); let mut vec = Vec::with_capacity(it.size_hint().0); - while let Some(v) = it.next()? { - vec.push(v); - } + it.for_each(|v| Ok(vec.push(v)))?; Ok(vec) } } @@ -1040,12 +1021,13 @@ where where I: IntoFallibleIterator, { - let mut it = it.into_fallible_iter(); + let it = it.into_fallible_iter(); let mut set = HashSet::default(); set.reserve(it.size_hint().0); - while let Some(v) = it.next()? { + it.for_each(|v| { set.insert(v); - } + Ok(()) + })?; Ok(set) } } @@ -1061,12 +1043,13 @@ where where I: IntoFallibleIterator, { - let mut it = it.into_fallible_iter(); + let it = it.into_fallible_iter(); let mut map = HashMap::default(); map.reserve(it.size_hint().0); - while let Some((k, v)) = it.next()? { + it.for_each(|(k, v)| { map.insert(k, v); - } + Ok(()) + })?; Ok(map) } } @@ -1081,11 +1064,12 @@ where where I: IntoFallibleIterator, { - let mut it = it.into_fallible_iter(); + let it = it.into_fallible_iter(); let mut set = BTreeSet::new(); - while let Some(v) = it.next()? { + it.for_each(|v| { set.insert(v); - } + Ok(()) + })?; Ok(set) } } @@ -1100,11 +1084,12 @@ where where I: IntoFallibleIterator, { - let mut it = it.into_fallible_iter(); + let it = it.into_fallible_iter(); let mut map = BTreeMap::new(); - while let Some((k, v)) = it.next()? { + it.for_each(|(k, v)| { map.insert(k, v); - } + Ok(()) + })?; Ok(map) } } @@ -1167,6 +1152,15 @@ where fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } + + #[inline] + fn fold(mut self, init: C, mut f: G) -> Result + where + G: FnMut(C, B) -> Result, + { + let map = &mut self.f; + self.it.fold(init, |b, v| f(b, map(v)?)) + } } impl DoubleEndedFallibleIterator for Map @@ -1244,6 +1238,51 @@ where ChainState::Back => self.back.count(), } } + + #[inline] + fn fold(self, init: B, mut f: F) -> Result + where + F: FnMut(B, T::Item) -> Result, + { + match self.state { + ChainState::Both => { + let init = self.front.fold(init, &mut f)?; + self.back.fold(init, f) + } + ChainState::Front => self.front.fold(init, f), + ChainState::Back => self.back.fold(init, f), + } + } + + #[inline] + fn find(&mut self, mut f: F) -> Result, T::Error> + where + F: FnMut(&T::Item) -> Result, + { + match self.state { + ChainState::Both => match self.front.find(&mut f)? { + Some(v) => Ok(Some(v)), + None => { + self.state = ChainState::Back; + self.back.find(f) + } + }, + ChainState::Front => self.front.find(f), + ChainState::Back => self.back.find(f), + } + } + + #[inline] + fn last(self) -> Result, T::Error> { + match self.state { + ChainState::Both => { + self.front.last()?; + self.back.last() + } + ChainState::Front => self.front.last(), + ChainState::Back => self.back.last(), + } + } } impl DoubleEndedFallibleIterator for Chain @@ -1290,8 +1329,11 @@ where } #[inline] - fn count(self) -> Result { - self.0.count() + fn fold(self, init: B, mut f: F) -> Result + where + F: FnMut(B, T) -> Result, + { + self.0.fold(init, |acc, v| f(acc, v.clone())) } } @@ -1339,6 +1381,14 @@ where fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } + + #[inline] + fn fold(mut self, init: B, mut f: F) -> Result + where + F: FnMut(B, T) -> Result, + { + self.0.try_fold(init, |acc, v| f(acc, v?)) + } } impl DoubleEndedFallibleIterator for Convert @@ -1390,6 +1440,31 @@ where fn count(self) -> Result { self.it.count() } + + #[inline] + fn nth(&mut self, n: usize) -> Result, I::Error> { + match self.it.nth(n)? { + Some(v) => { + let i = self.n + n; + self.n = i + 1; + Ok(Some((i, v))) + } + None => Ok(None), + } + } + + #[inline] + fn fold(self, init: B, mut f: F) -> Result + where + F: FnMut(B, (usize, I::Item)) -> Result, + { + let mut n = self.n; + self.it.fold(init, |acc, v| { + let i = n; + n += 1; + f(acc, (i, v)) + }) + } } /// An iterator which uses a fallible predicate to determine which values of the @@ -1423,6 +1498,24 @@ where fn size_hint(&self) -> (usize, Option) { (0, self.it.size_hint().1) } + + #[inline] + fn fold(self, init: B, mut f: G) -> Result + where + G: FnMut(B, I::Item) -> Result, + { + let mut predicate = self.f; + self.it.fold( + init, + |acc, v| { + if predicate(&v)? { + f(acc, v) + } else { + Ok(acc) + } + }, + ) + } } impl DoubleEndedFallibleIterator for Filter @@ -1473,6 +1566,18 @@ where fn size_hint(&self) -> (usize, Option) { (0, self.it.size_hint().1) } + + #[inline] + fn fold(self, init: C, mut f: G) -> Result + where + G: FnMut(C, B) -> Result, + { + let mut map = self.f; + self.it.fold(init, |acc, v| match map(v)? { + Some(v) => f(acc, v), + None => Ok(acc), + }) + } } impl DoubleEndedFallibleIterator for FilterMap @@ -1525,6 +1630,16 @@ where } } } + + #[inline] + fn fold(self, init: B, mut f: G) -> Result + where + G: FnMut(B, U::Item) -> Result, + { + convert(self.cur.into_iter().map(Ok)) + .chain(self.it.map(|i| Ok(i.into_fallible_iter()))) + .fold(init, |acc, it| it.fold(acc, &mut f)) + } } /// An iterator which flattens an iterator of iterators, yielding those iterators' elements. @@ -1574,6 +1689,16 @@ where } } } + + #[inline] + fn fold(self, init: B, mut f: F) -> Result + where + F: FnMut(B, Self::Item) -> Result, + { + convert(self.cur.into_iter().map(Ok)) + .chain(self.it.map(|i| Ok(i.into_fallible_iter()))) + .fold(init, |acc, it| it.fold(acc, &mut f)) + } } /// An iterator that yields `Ok(None)` forever after the underlying iterator @@ -1609,7 +1734,11 @@ where #[inline] fn size_hint(&self) -> (usize, Option) { - self.it.size_hint() + if self.done { + (0, Some(0)) + } else { + self.it.size_hint() + } } #[inline] @@ -1620,6 +1749,40 @@ where self.it.count() } } + + #[inline] + fn last(self) -> Result, I::Error> { + if self.done { + Ok(None) + } else { + self.it.last() + } + } + + #[inline] + fn nth(&mut self, n: usize) -> Result, I::Error> { + if self.done { + Ok(None) + } else { + let v = self.it.nth(n)?; + if v.is_none() { + self.done = true; + } + Ok(v) + } + } + + #[inline] + fn fold(self, init: B, f: F) -> Result + where + F: FnMut(B, I::Item) -> Result, + { + if self.done { + Ok(init) + } else { + self.it.fold(init, f) + } + } } /// An iterator which passes each element to a closure before returning it. @@ -1652,6 +1815,18 @@ where fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } + + #[inline] + fn fold(self, init: B, mut f: G) -> Result + where + G: FnMut(B, I::Item) -> Result, + { + let mut inspect = self.f; + self.it.fold(init, |acc, v| { + inspect(&v)?; + f(acc, v) + }) + } } impl DoubleEndedFallibleIterator for Inspect @@ -1740,6 +1915,16 @@ where fn count(mut self) -> Result { self.it.count().map_err(&mut self.f) } + + #[inline] + fn last(mut self) -> Result, B> { + self.it.last().map_err(&mut self.f) + } + + #[inline] + fn nth(&mut self, n: usize) -> Result, B> { + self.it.nth(n).map_err(&mut self.f) + } } impl DoubleEndedFallibleIterator for MapErr From f66cbbda70e9b007bbdd181a1167079126f50f58 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 22:02:54 -0800 Subject: [PATCH 31/34] Implement last in terms of fold --- src/lib.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4d8ed38..708ad77 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -147,15 +147,11 @@ pub trait FallibleIterator { /// Returns the last element of the iterator. #[inline] - fn last(mut self) -> Result, Self::Error> + fn last(self) -> Result, Self::Error> where Self: Sized, { - let mut last = None; - while let Some(e) = self.next()? { - last = Some(e); - } - Ok(last) + self.fold(None, |_, v| Ok(Some(v))) } /// Returns the `n`th element of the iterator. From a77f005547d99e8f1c05c1208037bc90edfb727b Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 9 Mar 2019 22:54:20 -0800 Subject: [PATCH 32/34] Add rfold --- src/lib.rs | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 708ad77..2be1f78 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -982,6 +982,19 @@ impl DoubleEndedFallibleIterator for Bo pub trait DoubleEndedFallibleIterator: FallibleIterator { /// Advances the end of the iterator, returning the last value. fn next_back(&mut self) -> Result, Self::Error>; + + /// Applies a function over the elements of the iterator in reverse order, producing a single final value. + #[inline] + fn rfold(mut self, mut init: B, mut f: F) -> Result + where + Self: Sized, + F: FnMut(B, Self::Item) -> Result, + { + while let Some(v) = self.next_back()? { + init = f(init, v)?; + } + Ok(init) + } } /// Conversion from a fallible iterator. @@ -1172,6 +1185,15 @@ where Err(e) => Err(e), } } + + #[inline] + fn rfold(self, init: C, mut f: G) -> Result + where + G: FnMut(C, B) -> Result, + { + let mut map = self.f; + self.it.rfold(init, |acc, v| f(acc, map(v)?)) + } } #[derive(Clone, Debug)] @@ -1300,6 +1322,21 @@ where ChainState::Back => self.back.next_back(), } } + + #[inline] + fn rfold(self, init: B, mut f: F) -> Result + where + F: FnMut(B, T::Item) -> Result, + { + match self.state { + ChainState::Both => { + let init = self.back.rfold(init, &mut f)?; + self.front.rfold(init, f) + } + ChainState::Front => self.front.rfold(init, f), + ChainState::Back => self.back.rfold(init, f), + } + } } /// An iterator which clones the elements of the underlying iterator. @@ -1342,6 +1379,14 @@ where fn next_back(&mut self) -> Result, I::Error> { self.0.next_back().map(|o| o.cloned()) } + + #[inline] + fn rfold(self, init: B, mut f: F) -> Result + where + F: FnMut(B, T) -> Result, + { + self.0.rfold(init, |acc, v| f(acc, v.clone())) + } } /// Converts an `Iterator>` into a `FallibleIterator`. @@ -1399,6 +1444,14 @@ where None => Ok(None), } } + + #[inline] + fn rfold(mut self, init: B, mut f: F) -> Result + where + F: FnMut(B, T) -> Result, + { + self.0.try_rfold(init, |acc, v| f(acc, v?)) + } } /// An iterator that yields the iteration count as well as the values of the @@ -1529,6 +1582,24 @@ where Ok(None) } + + #[inline] + fn rfold(self, init: B, mut f: G) -> Result + where + G: FnMut(B, I::Item) -> Result, + { + let mut predicate = self.f; + self.it.rfold( + init, + |acc, v| { + if predicate(&v)? { + f(acc, v) + } else { + Ok(acc) + } + }, + ) + } } /// An iterator which both filters and maps the values of the underlying @@ -1591,6 +1662,18 @@ where Ok(None) } + + #[inline] + fn rfold(self, init: C, mut f: G) -> Result + where + G: FnMut(C, B) -> Result, + { + let mut map = self.f; + self.it.rfold(init, |acc, v| match map(v)? { + Some(v) => f(acc, v), + None => Ok(acc), + }) + } } /// An iterator which maps each element to another iterator, yielding those iterator's elements. @@ -1840,6 +1923,18 @@ where None => Ok(None), } } + + #[inline] + fn rfold(self, init: B, mut f: G) -> Result + where + G: FnMut(B, I::Item) -> Result, + { + let mut inspect = self.f; + self.it.rfold(init, |acc, v| { + inspect(&v)?; + f(acc, v) + }) + } } /// A normal (non-fallible) iterator which wraps a fallible iterator. @@ -2009,6 +2104,14 @@ where fn count(self) -> Result { self.0.count() } + + #[inline] + fn fold(self, init: B, f: F) -> Result + where + F: FnMut(B, I::Item) -> Result, + { + self.0.rfold(init, f) + } } impl DoubleEndedFallibleIterator for Rev @@ -2019,6 +2122,14 @@ where fn next_back(&mut self) -> Result, I::Error> { self.0.next() } + + #[inline] + fn rfold(self, init: B, f: F) -> Result + where + F: FnMut(B, I::Item) -> Result, + { + self.0.fold(init, f) + } } /// An iterator which applies a stateful closure. From 247d721087317515ca4bb0e4a7110d447f042106 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 10 Mar 2019 14:27:55 -0700 Subject: [PATCH 33/34] Use try_fold to implement some methods --- src/lib.rs | 435 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 300 insertions(+), 135 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2be1f78..24c3c23 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,6 +101,33 @@ use crate::imports::*; #[cfg(test)] mod test; +enum FoldStop { + Break(T), + Err(E), +} + +impl From for FoldStop { + #[inline] + fn from(e: E) -> FoldStop { + FoldStop::Err(e) + } +} + +trait ResultExt { + fn unpack_fold(self) -> Result; +} + +impl ResultExt for Result> { + #[inline] + fn unpack_fold(self) -> Result { + match self { + Ok(v) => Ok(v), + Err(FoldStop::Break(v)) => Ok(v), + Err(FoldStop::Err(e)) => Err(e), + } + } +} + /// An `Iterator`-like trait that allows for calculation of items to fail. pub trait FallibleIterator { /// The type being iterated over. @@ -446,15 +473,27 @@ pub trait FallibleIterator { /// Applies a function over the elements of the iterator, producing a single /// final value. #[inline] - fn fold(mut self, mut init: B, mut f: F) -> Result + fn fold(mut self, init: B, f: F) -> Result where Self: Sized, F: FnMut(B, Self::Item) -> Result, + { + self.try_fold(init, f) + } + + /// Applies a function over the elements of the iterator, producing a single final value. + /// + /// This is used as the "base" of many methods on `FallibleIterator`. + #[inline] + fn try_fold(&mut self, mut init: B, mut f: F) -> Result + where + Self: Sized, + E: From, + F: FnMut(B, Self::Item) -> Result, { while let Some(v) = self.next()? { init = f(init, v)?; } - Ok(init) } @@ -465,13 +504,14 @@ pub trait FallibleIterator { Self: Sized, F: FnMut(Self::Item) -> Result, { - while let Some(v) = self.next()? { + self.try_fold((), |(), v| { if !f(v)? { - return Ok(false); + return Err(FoldStop::Break(false)); } - } - - Ok(true) + Ok(()) + }) + .map(|()| true) + .unpack_fold() } /// Determines if any element of this iterator matches a predicate. @@ -481,13 +521,14 @@ pub trait FallibleIterator { Self: Sized, F: FnMut(Self::Item) -> Result, { - while let Some(v) = self.next()? { + self.try_fold((), |(), v| { if f(v)? { - return Ok(true); + return Err(FoldStop::Break(true)); } - } - - Ok(false) + Ok(()) + }) + .map(|()| false) + .unpack_fold() } /// Returns the first element of the iterator that matches a predicate. @@ -497,13 +538,14 @@ pub trait FallibleIterator { Self: Sized, F: FnMut(&Self::Item) -> Result, { - while let Some(v) = self.next()? { + self.try_fold((), |(), v| { if f(&v)? { - return Ok(Some(v)); + return Err(FoldStop::Break(Some(v))); } - } - - Ok(None) + Ok(()) + }) + .map(|()| None) + .unpack_fold() } /// Applies a function to the elements of the iterator, returning the first non-`None` result. @@ -525,14 +567,14 @@ pub trait FallibleIterator { Self: Sized, F: FnMut(Self::Item) -> Result, { - let mut i = 0; - while let Some(v) = self.next()? { + self.try_fold(0, |n, v| { if f(v)? { - return Ok(Some(i)); + return Err(FoldStop::Break(Some(n))); } - i += 1; - } - Ok(None) + Ok(n + 1) + }) + .map(|_| None) + .unpack_fold() } /// Returns the maximal element of the iterator. @@ -985,10 +1027,23 @@ pub trait DoubleEndedFallibleIterator: FallibleIterator { /// Applies a function over the elements of the iterator in reverse order, producing a single final value. #[inline] - fn rfold(mut self, mut init: B, mut f: F) -> Result + fn rfold(mut self, init: B, f: F) -> Result where Self: Sized, F: FnMut(B, Self::Item) -> Result, + { + self.try_rfold(init, f) + } + + /// Applies a function over the elements of the iterator in reverse, producing a single final value. + /// + /// This is used as the "base" of many methods on `DoubleEndedFallibleIterator`. + #[inline] + fn try_rfold(&mut self, mut init: B, mut f: F) -> Result + where + Self: Sized, + E: From, + F: FnMut(B, Self::Item) -> Result, { while let Some(v) = self.next_back()? { init = f(init, v)?; @@ -1163,12 +1218,13 @@ where } #[inline] - fn fold(mut self, init: C, mut f: G) -> Result + fn try_fold(&mut self, init: C, mut f: G) -> Result where - G: FnMut(C, B) -> Result, + E: From, + G: FnMut(C, B) -> Result, { let map = &mut self.f; - self.it.fold(init, |b, v| f(b, map(v)?)) + self.it.try_fold(init, |b, v| f(b, map(v)?)) } } @@ -1187,12 +1243,13 @@ where } #[inline] - fn rfold(self, init: C, mut f: G) -> Result + fn try_rfold(&mut self, init: C, mut f: G) -> Result where - G: FnMut(C, B) -> Result, + E: From, + G: FnMut(C, B) -> Result, { - let mut map = self.f; - self.it.rfold(init, |acc, v| f(acc, map(v)?)) + let map = &mut self.f; + self.it.try_rfold(init, |acc, v| f(acc, map(v)?)) } } @@ -1258,17 +1315,19 @@ where } #[inline] - fn fold(self, init: B, mut f: F) -> Result + fn try_fold(&mut self, init: B, mut f: F) -> Result where - F: FnMut(B, T::Item) -> Result, + E: From, + F: FnMut(B, T::Item) -> Result, { match self.state { ChainState::Both => { - let init = self.front.fold(init, &mut f)?; - self.back.fold(init, f) + let init = self.front.try_fold(init, &mut f)?; + self.state = ChainState::Back; + self.back.try_fold(init, f) } - ChainState::Front => self.front.fold(init, f), - ChainState::Back => self.back.fold(init, f), + ChainState::Front => self.front.try_fold(init, f), + ChainState::Back => self.back.try_fold(init, f), } } @@ -1324,17 +1383,19 @@ where } #[inline] - fn rfold(self, init: B, mut f: F) -> Result + fn try_rfold(&mut self, init: B, mut f: F) -> Result where - F: FnMut(B, T::Item) -> Result, + E: From, + F: FnMut(B, T::Item) -> Result, { match self.state { ChainState::Both => { - let init = self.back.rfold(init, &mut f)?; - self.front.rfold(init, f) + let init = self.back.try_rfold(init, &mut f)?; + self.state = ChainState::Front; + self.front.try_rfold(init, f) } - ChainState::Front => self.front.rfold(init, f), - ChainState::Back => self.back.rfold(init, f), + ChainState::Front => self.front.try_rfold(init, f), + ChainState::Back => self.back.try_rfold(init, f), } } } @@ -1362,11 +1423,12 @@ where } #[inline] - fn fold(self, init: B, mut f: F) -> Result + fn try_fold(&mut self, init: B, mut f: F) -> Result where - F: FnMut(B, T) -> Result, + E: From, + F: FnMut(B, T) -> Result, { - self.0.fold(init, |acc, v| f(acc, v.clone())) + self.0.try_fold(init, |acc, v| f(acc, v.clone())) } } @@ -1381,11 +1443,12 @@ where } #[inline] - fn rfold(self, init: B, mut f: F) -> Result + fn try_rfold(&mut self, init: B, mut f: F) -> Result where - F: FnMut(B, T) -> Result, + E: From, + F: FnMut(B, T) -> Result, { - self.0.rfold(init, |acc, v| f(acc, v.clone())) + self.0.try_rfold(init, |acc, v| f(acc, v.clone())) } } @@ -1424,9 +1487,10 @@ where } #[inline] - fn fold(mut self, init: B, mut f: F) -> Result + fn try_fold(&mut self, init: B, mut f: F) -> Result where - F: FnMut(B, T) -> Result, + E2: From, + F: FnMut(B, T) -> Result, { self.0.try_fold(init, |acc, v| f(acc, v?)) } @@ -1446,9 +1510,10 @@ where } #[inline] - fn rfold(mut self, init: B, mut f: F) -> Result + fn try_rfold(&mut self, init: B, mut f: F) -> Result where - F: FnMut(B, T) -> Result, + E2: From, + F: FnMut(B, T) -> Result, { self.0.try_rfold(init, |acc, v| f(acc, v?)) } @@ -1503,14 +1568,15 @@ where } #[inline] - fn fold(self, init: B, mut f: F) -> Result + fn try_fold(&mut self, init: B, mut f: F) -> Result where - F: FnMut(B, (usize, I::Item)) -> Result, + E: From, + F: FnMut(B, (usize, I::Item)) -> Result, { - let mut n = self.n; - self.it.fold(init, |acc, v| { - let i = n; - n += 1; + let n = &mut self.n; + self.it.try_fold(init, |acc, v| { + let i = *n; + *n += 1; f(acc, (i, v)) }) } @@ -1534,13 +1600,16 @@ where #[inline] fn next(&mut self) -> Result, I::Error> { - while let Some(v) = self.it.next()? { - if (self.f)(&v)? { - return Ok(Some(v)); - } - } - - Ok(None) + let filter = &mut self.f; + self.it + .try_fold((), |(), v| { + if filter(&v)? { + return Err(FoldStop::Break(Some(v))); + } + Ok(()) + }) + .map(|()| None) + .unpack_fold() } #[inline] @@ -1549,12 +1618,13 @@ where } #[inline] - fn fold(self, init: B, mut f: G) -> Result + fn try_fold(&mut self, init: B, mut f: G) -> Result where - G: FnMut(B, I::Item) -> Result, + E: From, + G: FnMut(B, I::Item) -> Result, { - let mut predicate = self.f; - self.it.fold( + let predicate = &mut self.f; + self.it.try_fold( init, |acc, v| { if predicate(&v)? { @@ -1574,22 +1644,26 @@ where { #[inline] fn next_back(&mut self) -> Result, I::Error> { - while let Some(v) = self.it.next_back()? { - if (self.f)(&v)? { - return Ok(Some(v)); - } - } - - Ok(None) + let filter = &mut self.f; + self.it + .try_rfold((), |(), v| { + if filter(&v)? { + return Err(FoldStop::Break(Some(v))); + } + Ok(()) + }) + .map(|()| None) + .unpack_fold() } #[inline] - fn rfold(self, init: B, mut f: G) -> Result + fn try_rfold(&mut self, init: B, mut f: G) -> Result where - G: FnMut(B, I::Item) -> Result, + E: From, + G: FnMut(B, I::Item) -> Result, { - let mut predicate = self.f; - self.it.rfold( + let predicate = &mut self.f; + self.it.try_rfold( init, |acc, v| { if predicate(&v)? { @@ -1620,13 +1694,14 @@ where #[inline] fn next(&mut self) -> Result, I::Error> { - while let Some(v) = self.it.next()? { - if let Some(v) = (self.f)(v)? { - return Ok(Some(v)); - } - } - - Ok(None) + let map = &mut self.f; + self.it + .try_fold((), |(), v| match map(v)? { + Some(v) => Err(FoldStop::Break(Some(v))), + None => Ok(()), + }) + .map(|()| None) + .unpack_fold() } #[inline] @@ -1635,12 +1710,13 @@ where } #[inline] - fn fold(self, init: C, mut f: G) -> Result + fn try_fold(&mut self, init: C, mut f: G) -> Result where - G: FnMut(C, B) -> Result, + E: From, + G: FnMut(C, B) -> Result, { - let mut map = self.f; - self.it.fold(init, |acc, v| match map(v)? { + let map = &mut self.f; + self.it.try_fold(init, |acc, v| match map(v)? { Some(v) => f(acc, v), None => Ok(acc), }) @@ -1654,22 +1730,24 @@ where { #[inline] fn next_back(&mut self) -> Result, I::Error> { - while let Some(v) = self.it.next_back()? { - if let Some(v) = (self.f)(v)? { - return Ok(Some(v)); - } - } - - Ok(None) + let map = &mut self.f; + self.it + .try_rfold((), |(), v| match map(v)? { + Some(v) => Err(FoldStop::Break(Some(v))), + None => Ok(()), + }) + .map(|()| None) + .unpack_fold() } #[inline] - fn rfold(self, init: C, mut f: G) -> Result + fn try_rfold(&mut self, init: C, mut f: G) -> Result where - G: FnMut(C, B) -> Result, + E: From, + G: FnMut(C, B) -> Result, { - let mut map = self.f; - self.it.rfold(init, |acc, v| match map(v)? { + let map = &mut self.f; + self.it.try_rfold(init, |acc, v| match map(v)? { Some(v) => f(acc, v), None => Ok(acc), }) @@ -1711,13 +1789,28 @@ where } #[inline] - fn fold(self, init: B, mut f: G) -> Result + fn try_fold(&mut self, init: B, mut f: G) -> Result where - G: FnMut(B, U::Item) -> Result, + E: From, + G: FnMut(B, U::Item) -> Result, { - convert(self.cur.into_iter().map(Ok)) - .chain(self.it.map(|i| Ok(i.into_fallible_iter()))) - .fold(init, |acc, it| it.fold(acc, &mut f)) + let mut acc = init; + if let Some(cur) = &mut self.cur { + acc = cur.try_fold(acc, &mut f)?; + self.cur = None; + } + + let cur = &mut self.cur; + self.it.try_fold(acc, |acc, v| { + let mut it = v.into_fallible_iter(); + match it.try_fold(acc, &mut f) { + Ok(acc) => Ok(acc), + Err(e) => { + *cur = Some(it); + Err(e) + } + } + }) } } @@ -1770,13 +1863,28 @@ where } #[inline] - fn fold(self, init: B, mut f: F) -> Result + fn try_fold(&mut self, init: B, mut f: G) -> Result where - F: FnMut(B, Self::Item) -> Result, + E: From, + G: FnMut(B, Self::Item) -> Result, { - convert(self.cur.into_iter().map(Ok)) - .chain(self.it.map(|i| Ok(i.into_fallible_iter()))) - .fold(init, |acc, it| it.fold(acc, &mut f)) + let mut acc = init; + if let Some(cur) = &mut self.cur { + acc = cur.try_fold(acc, &mut f)?; + self.cur = None; + } + + let cur = &mut self.cur; + self.it.try_fold(acc, |acc, v| { + let mut it = v.into_fallible_iter(); + match it.try_fold(acc, &mut f) { + Ok(acc) => Ok(acc), + Err(e) => { + *cur = Some(it); + Err(e) + } + } + }) } } @@ -1801,13 +1909,12 @@ where return Ok(None); } - match self.it.next() { - Ok(Some(i)) => Ok(Some(i)), - Ok(None) => { + match self.it.next()? { + Some(i) => Ok(Some(i)), + None => { self.done = true; Ok(None) } - Err(e) => Err(e), } } @@ -1852,14 +1959,15 @@ where } #[inline] - fn fold(self, init: B, f: F) -> Result + fn try_fold(&mut self, init: B, f: F) -> Result where - F: FnMut(B, I::Item) -> Result, + E: From, + F: FnMut(B, I::Item) -> Result, { if self.done { Ok(init) } else { - self.it.fold(init, f) + self.it.try_fold(init, f) } } } @@ -1896,12 +2004,13 @@ where } #[inline] - fn fold(self, init: B, mut f: G) -> Result + fn try_fold(&mut self, init: B, mut f: G) -> Result where - G: FnMut(B, I::Item) -> Result, + E: From, + G: FnMut(B, I::Item) -> Result, { - let mut inspect = self.f; - self.it.fold(init, |acc, v| { + let inspect = &mut self.f; + self.it.try_fold(init, |acc, v| { inspect(&v)?; f(acc, v) }) @@ -1925,12 +2034,13 @@ where } #[inline] - fn rfold(self, init: B, mut f: G) -> Result + fn try_rfold(&mut self, init: B, mut f: G) -> Result where - G: FnMut(B, I::Item) -> Result, + E: From, + G: FnMut(B, I::Item) -> Result, { - let mut inspect = self.f; - self.it.rfold(init, |acc, v| { + let inspect = &mut self.f; + self.it.try_rfold(init, |acc, v| { inspect(&v)?; f(acc, v) }) @@ -2016,6 +2126,20 @@ where fn nth(&mut self, n: usize) -> Result, B> { self.it.nth(n).map_err(&mut self.f) } + + #[inline] + fn try_fold(&mut self, init: C, mut f: G) -> Result + where + E: From, + G: FnMut(C, I::Item) -> Result, + { + self.it + .try_fold(init, |acc, v| f(acc, v).map_err(MappedErr::Fold)) + .map_err(|e| match e { + MappedErr::It(e) => (self.f)(e).into(), + MappedErr::Fold(e) => e, + }) + } } impl DoubleEndedFallibleIterator for MapErr @@ -2027,6 +2151,32 @@ where fn next_back(&mut self) -> Result, B> { self.it.next_back().map_err(&mut self.f) } + + #[inline] + fn try_rfold(&mut self, init: C, mut f: G) -> Result + where + E: From, + G: FnMut(C, I::Item) -> Result, + { + self.it + .try_rfold(init, |acc, v| f(acc, v).map_err(MappedErr::Fold)) + .map_err(|e| match e { + MappedErr::It(e) => (self.f)(e).into(), + MappedErr::Fold(e) => e, + }) + } +} + +enum MappedErr { + It(T), + Fold(U), +} + +impl From for MappedErr { + #[inline] + fn from(t: T) -> MappedErr { + MappedErr::It(t) + } } /// An iterator which can look at the next element without consuming it. @@ -2076,6 +2226,19 @@ where } hint } + + #[inline] + fn try_fold(&mut self, init: B, mut f: F) -> Result + where + E: From, + F: FnMut(B, I::Item) -> Result, + { + let mut acc = init; + if let Some(v) = self.next.take() { + acc = f(acc, v)?; + } + self.it.try_fold(acc, f) + } } /// An iterator which yields elements of the underlying iterator in reverse @@ -2106,11 +2269,12 @@ where } #[inline] - fn fold(self, init: B, f: F) -> Result + fn try_fold(&mut self, init: B, f: F) -> Result where - F: FnMut(B, I::Item) -> Result, + E: From, + F: FnMut(B, I::Item) -> Result, { - self.0.rfold(init, f) + self.0.try_rfold(init, f) } } @@ -2124,11 +2288,12 @@ where } #[inline] - fn rfold(self, init: B, f: F) -> Result + fn try_rfold(&mut self, init: B, f: F) -> Result where - F: FnMut(B, I::Item) -> Result, + E: From, + F: FnMut(B, I::Item) -> Result, { - self.0.fold(init, f) + self.0.try_fold(init, f) } } @@ -2438,4 +2603,4 @@ where } } -fn _is_object_safe(_: &dyn FallibleIterator) {} +fn _is_object_safe(_: &dyn DoubleEndedFallibleIterator) {} From 03b701c04b37fcd1ab1045c4623542606abf378b Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 10 Mar 2019 14:36:40 -0700 Subject: [PATCH 34/34] Release v0.2.0 --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ src/lib.rs | 16 ++++++++-------- 2 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c2cb0c6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,26 @@ +# Change Log + +## [Unreleased] + +## [v0.2.0] - 2019-03-10 + +### Changed + +* All closures used by adaptor methods now return `Result`s. +* `FromFallibleIterator::from_fallible_iterator` has been renamed to `from_fallible_iter` and now takes an + `IntoFallibleIterator`. +* `IntoFallibleIterator::into_fallible_iterator` has been renamed to `into_fallible_iter`. +* `IntoFallibleIterator::IntoIter` has been renamed to `IntoFallibleIter`. + +### Removed + +* `FallibleIterator::and_then` has been removed as `FallibleIterator::map` is now equivalent. + +### Added + +* Added `step_by`, `for_each`, `skip_while`, `take_while`, `skip`, `scan`, `flat_map`, `flatten`, `inspect`, + `partition`, `find_map`, `max_by`, `min_by`, `unzip`, `cycle`, and `try_fold` to `FallibleIterator`. +* Added `rfold` and `try_rfold` to `DoubleEndedFallibleIterator`. + +[Unreleased]: https://github.com/sfackler/rust-fallible-iterator/compare/v0.2.0...master +[v0.2.0]: https://github.com/sfackler/rust-fallible-iterator/compare/v0.1.5...v0.2.0 diff --git a/src/lib.rs b/src/lib.rs index 24c3c23..f5f77b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,7 +63,7 @@ //! let big_numbers = numbers.filter(|n| Ok(u64::from_str(n)? > 100)); //! assert!(big_numbers.count().is_err()); //! ``` -#![doc(html_root_url = "https://docs.rs/fallible-iterator/0.1")] +#![doc(html_root_url = "https://docs.rs/fallible-iterator/0.2")] #![warn(missing_docs)] #![cfg_attr(feature = "alloc", feature(alloc))] #![no_std] @@ -444,7 +444,7 @@ pub trait FallibleIterator { T: FromFallibleIterator, Self: Sized, { - T::from_fallible_iterator(self) + T::from_fallible_iter(self) } /// Transforms the iterator into two collections, partitioning elements by a closure. @@ -1055,7 +1055,7 @@ pub trait DoubleEndedFallibleIterator: FallibleIterator { /// Conversion from a fallible iterator. pub trait FromFallibleIterator: Sized { /// Creates a value from a fallible iterator. - fn from_fallible_iterator(it: I) -> Result + fn from_fallible_iter(it: I) -> Result where I: IntoFallibleIterator; } @@ -1063,7 +1063,7 @@ pub trait FromFallibleIterator: Sized { #[cfg(any(feature = "std", feature = "alloc"))] impl FromFallibleIterator for Vec { #[inline] - fn from_fallible_iterator(it: I) -> Result, I::Error> + fn from_fallible_iter(it: I) -> Result, I::Error> where I: IntoFallibleIterator, { @@ -1081,7 +1081,7 @@ where S: BuildHasher + Default, { #[inline] - fn from_fallible_iterator(it: I) -> Result, I::Error> + fn from_fallible_iter(it: I) -> Result, I::Error> where I: IntoFallibleIterator, { @@ -1103,7 +1103,7 @@ where S: BuildHasher + Default, { #[inline] - fn from_fallible_iterator(it: I) -> Result, I::Error> + fn from_fallible_iter(it: I) -> Result, I::Error> where I: IntoFallibleIterator, { @@ -1124,7 +1124,7 @@ where T: Ord, { #[inline] - fn from_fallible_iterator(it: I) -> Result, I::Error> + fn from_fallible_iter(it: I) -> Result, I::Error> where I: IntoFallibleIterator, { @@ -1144,7 +1144,7 @@ where K: Ord, { #[inline] - fn from_fallible_iterator(it: I) -> Result, I::Error> + fn from_fallible_iter(it: I) -> Result, I::Error> where I: IntoFallibleIterator, {