summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWoohyun Jung <wh0705.jung@samsung.com>2023-03-14 18:35:04 +0900
committerWoohyun Jung <wh0705.jung@samsung.com>2023-03-14 18:35:04 +0900
commit575b828679a49397abd7fb93b504d0532dd80444 (patch)
treedfd95ab0ac90586a2cccf95bcc760dc88b9bd47c
downloadrust-fallible-iterator-upstream.tar.gz
rust-fallible-iterator-upstream.tar.bz2
rust-fallible-iterator-upstream.zip
Import fallible-iterator 0.2.0upstream/0.2.0upstream
-rw-r--r--.cargo_vcs_info.json5
-rw-r--r--.circleci/config.yml60
-rw-r--r--.gitignore4
-rw-r--r--CHANGELOG.md26
-rw-r--r--Cargo.toml27
-rw-r--r--Cargo.toml.orig15
-rw-r--r--LICENSE-APACHE202
-rw-r--r--LICENSE-MIT19
-rw-r--r--README.md15
-rw-r--r--src/lib.rs2606
-rw-r--r--src/test.rs455
11 files changed, 3434 insertions, 0 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..37ca5ef
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+ "git": {
+ "sha1": "03b701c04b37fcd1ab1045c4623542606abf378b"
+ }
+}
diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..cf9d2e4
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,60 @@
+restore_registry: &RESTORE_REGISTRY
+ restore_cache:
+ key: registry
+save_registry: &SAVE_REGISTRY
+ save_cache:
+ key: registry-{{ .BuildNum }}
+ paths:
+ - /usr/local/cargo/registry/index
+deps_key: &DEPS_KEY
+ key: deps-{{ checksum "~/rust-version" }}-{{ checksum "Cargo.lock" }}
+restore_deps: &RESTORE_DEPS
+ restore_cache:
+ <<: *DEPS_KEY
+save_deps: &SAVE_DEPS
+ save_cache:
+ <<: *DEPS_KEY
+ paths:
+ - target
+ - /usr/local/cargo/registry/cache
+
+version: 2
+jobs:
+ stable:
+ docker:
+ - image: rust:1.33.0
+ environment:
+ RUSTFLAGS: -D warnings
+ working_directory: ~/build
+ steps:
+ - checkout
+ - *RESTORE_REGISTRY
+ - run: cargo generate-lockfile
+ - *SAVE_REGISTRY
+ - run: rustc --version > ~/rust-version
+ - *RESTORE_DEPS
+ - run: cargo test
+ - run: cargo test --features std
+ - *SAVE_DEPS
+ nightly:
+ docker:
+ - image: rustlang/rust:nightly
+ environment:
+ RUSTFLAGS: -D warnings
+ working_directory: ~/build
+ steps:
+ - checkout
+ - *RESTORE_REGISTRY
+ - run: cargo generate-lockfile
+ - *SAVE_REGISTRY
+ - run: rustc --version > ~/rust-version
+ - *RESTORE_DEPS
+ - run: cargo test --features alloc
+ - *SAVE_DEPS
+
+workflows:
+ version: 2
+ tests:
+ jobs:
+ - stable
+ - nightly
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..03814ae
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+target
+Cargo.lock
+.idea/
+*.iml
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/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..b7a15c1
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,27 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "fallible-iterator"
+version = "0.2.0"
+authors = ["Steven Fackler <sfackler@gmail.com>"]
+description = "Fallible iterator traits"
+readme = "README.md"
+categories = ["algorithms", "no-std"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/sfackler/rust-fallible-iterator"
+
+[features]
+alloc = []
+default = ["std"]
+std = []
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..e8fd7e9
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,15 @@
+[package]
+name = "fallible-iterator"
+version = "0.2.0"
+authors = ["Steven Fackler <sfackler@gmail.com>"]
+edition = "2018"
+license = "MIT/Apache-2.0"
+description = "Fallible iterator traits"
+repository = "https://github.com/sfackler/rust-fallible-iterator"
+readme = "README.md"
+categories = ["algorithms", "no-std"]
+
+[features]
+alloc = []
+std = []
+default = ["std"]
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
new file mode 100644
index 0000000..8f71f43
--- /dev/null
+++ b/LICENSE-APACHE
@@ -0,0 +1,202 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..a7cfbe0
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,19 @@
+Copyright (c) 2015 The rust-openssl-verify Developers
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e7a4af2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+# rust-fallible-iterator
+
+[![CircleCI](https://circleci.com/gh/sfackler/rust-fallible-iterator.svg?style=shield)](https://circleci.com/gh/sfackler/rust-fallible-iterator)
+
+[Documentation](https://sfackler.github.io/rust-fallible-iterator/doc/v0.1.3/fallible_iterator)
+
+"Fallible" iterators for Rust.
+
+## Features
+
+If the `std` or `alloc` features are enabled, this crate provides implementations for
+`Box`, `Vec`, `BTreeMap`, and `BTreeSet`. If the `std` feature is enabled, this crate
+additionally provides implementations for `HashMap` and `HashSet`.
+
+If the `std` feature is disabled, this crate does not depend on `libstd`.
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..f5f77b2
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,2606 @@
+//! "Fallible" iterators.
+//!
+//! The iterator APIs in the Rust standard library do not support iteration
+//! that can fail in a first class manner. These iterators are typically modeled
+//! as iterating over `Result<T, E>` values; for example, the `Lines` iterator
+//! returns `io::Result<String>`s. When simply iterating over these types, the
+//! value being iterated over must be unwrapped in some way before it can be
+//! used:
+//!
+//! ```ignore
+//! for line in reader.lines() {
+//! let line = line?;
+//! // work with line
+//! }
+//! ```
+//!
+//! In addition, many of the additional methods on the `Iterator` trait will
+//! not behave properly in the presence of errors when working with these kinds
+//! of iterators. For example, if one wanted to count the number of lines of
+//! text in a `Read`er, this might be a way to go about it:
+//!
+//! ```ignore
+//! let count = reader.lines().count();
+//! ```
+//!
+//! This will return the proper value when the reader operates successfully, but
+//! if it encounters an IO error, the result will either be slightly higher than
+//! expected if the error is transient, or it may run forever if the error is
+//! returned repeatedly!
+//!
+//! In contrast, a fallible iterator is built around the concept that a call to
+//! `next` can fail. The trait has an additional `Error` associated type in
+//! addition to the `Item` type, and `next` returns `Result<Option<Self::Item>,
+//! Self::Error>` rather than `Option<Self::Item>`. Methods like `count` return
+//! `Result`s as well.
+//!
+//! This does mean that fallible iterators are incompatible with Rust's `for`
+//! loop syntax, but `while let` loops offer a similar level of ergonomics:
+//!
+//! ```ignore
+//! while let Some(item) = iter.next()? {
+//! // 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<T, Self::Error>` 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<bool, Self::Error>`:
+//!
+//! ```
+//! # 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<Error>>));
+//! 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.2")]
+#![warn(missing_docs)]
+#![cfg_attr(feature = "alloc", feature(alloc))]
+#![no_std]
+
+use core::cmp::{self, Ordering};
+use core::iter;
+
+#[cfg(all(feature = "alloc", not(feature = "std")))]
+#[cfg_attr(test, macro_use)]
+extern crate alloc;
+
+#[cfg(all(feature = "alloc", not(feature = "std")))]
+mod imports {
+ pub use alloc::boxed::Box;
+ pub use alloc::collections::btree_map::BTreeMap;
+ pub use alloc::collections::btree_set::BTreeSet;
+ pub use alloc::vec::Vec;
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(test, macro_use)]
+extern crate std;
+
+#[cfg(feature = "std")]
+mod imports {
+ pub use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
+ pub use std::hash::{BuildHasher, Hash};
+ pub use std::prelude::v1::*;
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+use crate::imports::*;
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+#[cfg(test)]
+mod test;
+
+enum FoldStop<T, E> {
+ Break(T),
+ Err(E),
+}
+
+impl<T, E> From<E> for FoldStop<T, E> {
+ #[inline]
+ fn from(e: E) -> FoldStop<T, E> {
+ FoldStop::Err(e)
+ }
+}
+
+trait ResultExt<T, E> {
+ fn unpack_fold(self) -> Result<T, E>;
+}
+
+impl<T, E> ResultExt<T, E> for Result<T, FoldStop<T, E>> {
+ #[inline]
+ fn unpack_fold(self) -> Result<T, E> {
+ 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.
+ type Item;
+
+ /// The error type.
+ type Error;
+
+ /// Advances the iterator and returns the next value.
+ ///
+ /// Returns `Ok(None)` when iteration is finished.
+ ///
+ /// The behavior of calling this method after a previous call has returned
+ /// `Ok(None)` or `Err` is implemenetation defined.
+ fn next(&mut self) -> Result<Option<Self::Item>, Self::Error>;
+
+ /// Returns bounds on the remaining length of the iterator.
+ ///
+ /// Specifically, the first half of the returned tuple is a lower bound and
+ /// the second half is an upper bound.
+ ///
+ /// For the upper bound, `None` indicates that the upper bound is either
+ /// unknown or larger than can be represented as a `usize`.
+ ///
+ /// Both bounds assume that all remaining calls to `next` succeed. That is,
+ /// `next` could return an `Err` in fewer calls than specified by the lower
+ /// bound.
+ ///
+ /// The default implementation returns `(0, None)`, which is correct for
+ /// any iterator.
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (0, None)
+ }
+
+ /// Consumes the iterator, returning the number of remaining items.
+ #[inline]
+ fn count(self) -> Result<usize, Self::Error>
+ where
+ Self: Sized,
+ {
+ self.fold(0, |n, _| Ok(n + 1))
+ }
+
+ /// Returns the last element of the iterator.
+ #[inline]
+ fn last(self) -> Result<Option<Self::Item>, Self::Error>
+ where
+ Self: Sized,
+ {
+ self.fold(None, |_, v| Ok(Some(v)))
+ }
+
+ /// Returns the `n`th element of the iterator.
+ #[inline]
+ fn nth(&mut self, mut n: usize) -> Result<Option<Self::Item>, Self::Error> {
+ while let Some(e) = self.next()? {
+ if n == 0 {
+ return Ok(Some(e));
+ }
+ n -= 1;
+ }
+ 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<Self>
+ 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]
+ fn chain<I>(self, it: I) -> Chain<Self, I>
+ where
+ I: IntoFallibleIterator<Item = Self::Item, Error = Self::Error>,
+ Self: Sized,
+ {
+ Chain {
+ front: self,
+ back: it,
+ state: ChainState::Both,
+ }
+ }
+
+ /// Returns an iterator that yields pairs of this iterator's and another
+ /// iterator's values.
+ #[inline]
+ fn zip<I>(self, o: I) -> Zip<Self, I::IntoFallibleIter>
+ where
+ Self: Sized,
+ I: IntoFallibleIterator<Error = Self::Error>,
+ {
+ Zip(self, o.into_fallible_iter())
+ }
+
+ /// Returns an iterator which applies a fallible transform to the elements
+ /// of the underlying iterator.
+ #[inline]
+ fn map<F, B>(self, f: F) -> Map<Self, F>
+ where
+ Self: Sized,
+ F: FnMut(Self::Item) -> Result<B, Self::Error>,
+ {
+ Map { it: self, f: f }
+ }
+
+ /// Calls a fallible closure on each element of an iterator.
+ #[inline]
+ fn for_each<F>(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.
+ #[inline]
+ fn filter<F>(self, f: F) -> Filter<Self, F>
+ where
+ Self: Sized,
+ F: FnMut(&Self::Item) -> Result<bool, Self::Error>,
+ {
+ Filter { it: self, f: f }
+ }
+
+ /// Returns an iterator which both filters and maps. The closure may fail;
+ /// such failures are passed along to the consumer.
+ #[inline]
+ fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
+ where
+ Self: Sized,
+ F: FnMut(Self::Item) -> Result<Option<B>, Self::Error>,
+ {
+ FilterMap { it: self, f: f }
+ }
+
+ /// Returns an iterator which yields the current iteration count as well
+ /// as the value.
+ #[inline]
+ fn enumerate(self) -> Enumerate<Self>
+ where
+ Self: Sized,
+ {
+ Enumerate { it: self, n: 0 }
+ }
+
+ /// Returns an iterator that can peek at the next element without consuming
+ /// it.
+ #[inline]
+ fn peekable(self) -> Peekable<Self>
+ where
+ Self: Sized,
+ {
+ Peekable {
+ it: self,
+ next: None,
+ }
+ }
+
+ /// Returns an iterator that skips elements based on a predicate.
+ #[inline]
+ fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
+ where
+ Self: Sized,
+ P: FnMut(&Self::Item) -> Result<bool, Self::Error>,
+ {
+ SkipWhile {
+ it: self,
+ flag: false,
+ predicate,
+ }
+ }
+
+ /// Returns an iterator that yields elements based on a predicate.
+ #[inline]
+ fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
+ where
+ Self: Sized,
+ P: FnMut(&Self::Item) -> Result<bool, Self::Error>,
+ {
+ TakeWhile {
+ it: self,
+ flag: false,
+ predicate,
+ }
+ }
+
+ /// Returns an iterator which skips the first `n` values of this iterator.
+ #[inline]
+ fn skip(self, n: usize) -> Skip<Self>
+ where
+ Self: Sized,
+ {
+ Skip { it: self, n }
+ }
+
+ /// Returns an iterator that yields only the first `n` values of this
+ /// iterator.
+ #[inline]
+ fn take(self, n: usize) -> Take<Self>
+ where
+ Self: Sized,
+ {
+ Take {
+ it: self,
+ remaining: n,
+ }
+ }
+
+ /// Returns an iterator which applies a stateful map to values of this
+ /// iterator.
+ #[inline]
+ fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
+ where
+ Self: Sized,
+ F: FnMut(&mut St, Self::Item) -> Result<Option<B>, Self::Error>,
+ {
+ Scan {
+ it: self,
+ f,
+ state: initial_state,
+ }
+ }
+
+ /// Returns an iterator which maps this iterator's elements to iterators, yielding those iterators' values.
+ #[inline]
+ fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
+ where
+ Self: Sized,
+ U: IntoFallibleIterator<Error = Self::Error>,
+ F: FnMut(Self::Item) -> Result<U, Self::Error>,
+ {
+ FlatMap {
+ it: self.map(f),
+ cur: None,
+ }
+ }
+
+ /// Returns an iterator which flattens an iterator of iterators, yielding those iterators' values.
+ #[inline]
+ fn flatten(self) -> Flatten<Self>
+ where
+ Self: Sized,
+ Self::Item: IntoFallibleIterator<Error = Self::Error>,
+ {
+ Flatten {
+ it: self,
+ cur: None,
+ }
+ }
+
+ /// Returns an iterator which yields this iterator's elements and ends after
+ /// the first `Ok(None)`.
+ ///
+ /// The behavior of calling `next` after it has previously returned
+ /// `Ok(None)` is normally unspecified. The iterator returned by this method
+ /// guarantees that `Ok(None)` will always be returned.
+ #[inline]
+ fn fuse(self) -> Fuse<Self>
+ where
+ Self: Sized,
+ {
+ Fuse {
+ it: self,
+ done: false,
+ }
+ }
+
+ /// Returns an iterator which passes each element to a closure before returning it.
+ #[inline]
+ fn inspect<F>(self, f: F) -> Inspect<Self, F>
+ 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
+ /// 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<T>(self) -> Result<T, Self::Error>
+ where
+ T: FromFallibleIterator<Self::Item>,
+ Self: Sized,
+ {
+ T::from_fallible_iter(self)
+ }
+
+ /// Transforms the iterator into two collections, partitioning elements by a closure.
+ #[inline]
+ fn partition<B, F>(self, mut f: F) -> Result<(B, B), Self::Error>
+ where
+ Self: Sized,
+ B: Default + Extend<Self::Item>,
+ F: FnMut(&Self::Item) -> Result<bool, Self::Error>,
+ {
+ 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.
+ #[inline]
+ fn fold<B, F>(mut self, init: B, f: F) -> Result<B, Self::Error>
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> Result<B, Self::Error>,
+ {
+ 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<B, E, F>(&mut self, mut init: B, mut f: F) -> Result<B, E>
+ where
+ Self: Sized,
+ E: From<Self::Error>,
+ F: FnMut(B, Self::Item) -> Result<B, E>,
+ {
+ while let Some(v) = self.next()? {
+ init = f(init, v)?;
+ }
+ Ok(init)
+ }
+
+ /// Determines if all elements of this iterator match a predicate.
+ #[inline]
+ fn all<F>(&mut self, mut f: F) -> Result<bool, Self::Error>
+ where
+ Self: Sized,
+ F: FnMut(Self::Item) -> Result<bool, Self::Error>,
+ {
+ self.try_fold((), |(), v| {
+ if !f(v)? {
+ return Err(FoldStop::Break(false));
+ }
+ Ok(())
+ })
+ .map(|()| true)
+ .unpack_fold()
+ }
+
+ /// Determines if any element of this iterator matches a predicate.
+ #[inline]
+ fn any<F>(&mut self, mut f: F) -> Result<bool, Self::Error>
+ where
+ Self: Sized,
+ F: FnMut(Self::Item) -> Result<bool, Self::Error>,
+ {
+ self.try_fold((), |(), v| {
+ if f(v)? {
+ return Err(FoldStop::Break(true));
+ }
+ Ok(())
+ })
+ .map(|()| false)
+ .unpack_fold()
+ }
+
+ /// Returns the first element of the iterator that matches a predicate.
+ #[inline]
+ fn find<F>(&mut self, mut f: F) -> Result<Option<Self::Item>, Self::Error>
+ where
+ Self: Sized,
+ F: FnMut(&Self::Item) -> Result<bool, Self::Error>,
+ {
+ self.try_fold((), |(), v| {
+ if f(&v)? {
+ return Err(FoldStop::Break(Some(v)));
+ }
+ Ok(())
+ })
+ .map(|()| None)
+ .unpack_fold()
+ }
+
+ /// Applies a function to the elements of the iterator, returning the first non-`None` result.
+ #[inline]
+ fn find_map<B, F>(&mut self, f: F) -> Result<Option<B>, Self::Error>
+ where
+ Self: Sized,
+ F: FnMut(Self::Item) -> Result<Option<B>, 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.
+ #[inline]
+ fn position<F>(&mut self, mut f: F) -> Result<Option<usize>, Self::Error>
+ where
+ Self: Sized,
+ F: FnMut(Self::Item) -> Result<bool, Self::Error>,
+ {
+ self.try_fold(0, |n, v| {
+ if f(v)? {
+ return Err(FoldStop::Break(Some(n)));
+ }
+ Ok(n + 1)
+ })
+ .map(|_| None)
+ .unpack_fold()
+ }
+
+ /// Returns the maximal element of the iterator.
+ #[inline]
+ fn max(self) -> Result<Option<Self::Item>, Self::Error>
+ where
+ Self: Sized,
+ Self::Item: Ord,
+ {
+ self.max_by(|a, b| Ok(a.cmp(b)))
+ }
+
+ /// Returns the element of the iterator which gives the maximum value from
+ /// the function.
+ #[inline]
+ fn max_by_key<B, F>(mut self, mut f: F) -> Result<Option<Self::Item>, Self::Error>
+ where
+ Self: Sized,
+ B: Ord,
+ F: FnMut(&Self::Item) -> Result<B, Self::Error>,
+ {
+ let max = match self.next()? {
+ Some(v) => (f(&v)?, v),
+ None => return Ok(None),
+ };
+
+ self.fold(max, |(key, max), v| {
+ let new_key = f(&v)?;
+ if key > new_key {
+ Ok((key, max))
+ } else {
+ Ok((new_key, v))
+ }
+ })
+ .map(|v| Some(v.1))
+ }
+
+ /// Returns the element that gives the maximum value with respect to the function.
+ #[inline]
+ fn max_by<F>(mut self, mut f: F) -> Result<Option<Self::Item>, Self::Error>
+ where
+ Self: Sized,
+ F: FnMut(&Self::Item, &Self::Item) -> Result<Ordering, Self::Error>,
+ {
+ let max = match self.next()? {
+ Some(v) => v,
+ None => return Ok(None),
+ };
+
+ self.fold(max, |max, v| {
+ if f(&max, &v)? == Ordering::Greater {
+ Ok(max)
+ } else {
+ Ok(v)
+ }
+ })
+ .map(Some)
+ }
+
+ /// Returns the minimal element of the iterator.
+ #[inline]
+ fn min(self) -> Result<Option<Self::Item>, Self::Error>
+ where
+ Self: Sized,
+ Self::Item: Ord,
+ {
+ self.min_by(|a, b| Ok(a.cmp(b)))
+ }
+
+ /// Returns the element of the iterator which gives the minimum value from
+ /// the function.
+ #[inline]
+ fn min_by_key<B, F>(mut self, mut f: F) -> Result<Option<Self::Item>, Self::Error>
+ where
+ Self: Sized,
+ B: Ord,
+ F: FnMut(&Self::Item) -> Result<B, Self::Error>,
+ {
+ let min = match self.next()? {
+ Some(v) => (f(&v)?, v),
+ None => return Ok(None),
+ };
+
+ self.fold(min, |(key, min), v| {
+ let new_key = f(&v)?;
+ if key < new_key {
+ Ok((key, min))
+ } else {
+ Ok((new_key, v))
+ }
+ })
+ .map(|v| Some(v.1))
+ }
+
+ /// Returns the element that gives the minimum value with respect to the function.
+ #[inline]
+ fn min_by<F>(mut self, mut f: F) -> Result<Option<Self::Item>, Self::Error>
+ where
+ Self: Sized,
+ F: FnMut(&Self::Item, &Self::Item) -> Result<Ordering, Self::Error>,
+ {
+ let min = match self.next()? {
+ Some(v) => v,
+ None => return Ok(None),
+ };
+
+ self.fold(min, |min, v| {
+ if f(&min, &v)? == Ordering::Less {
+ Ok(min)
+ } else {
+ Ok(v)
+ }
+ })
+ .map(Some)
+ }
+
+ /// Returns an iterator that yields this iterator's items in the opposite
+ /// order.
+ #[inline]
+ fn rev(self) -> Rev<Self>
+ where
+ Self: Sized + DoubleEndedFallibleIterator,
+ {
+ Rev(self)
+ }
+
+ /// Converts an iterator of pairs into a pair of containers.
+ #[inline]
+ fn unzip<A, B, FromA, FromB>(self) -> Result<(FromA, FromB), Self::Error>
+ where
+ Self: Sized + FallibleIterator<Item = (A, B)>,
+ FromA: Default + Extend<A>,
+ FromB: Default + Extend<B>,
+ {
+ 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<Self>
+ where
+ Self: Sized + FallibleIterator<Item = &'a T>,
+ T: 'a + Clone,
+ {
+ Cloned(self)
+ }
+
+ /// Returns an iterator which repeas this iterator endlessly.
+ #[inline]
+ fn cycle(self) -> Cycle<Self>
+ where
+ Self: Sized + Clone,
+ {
+ Cycle {
+ it: self.clone(),
+ cur: self,
+ }
+ }
+
+ /// Lexicographically compares the elements of this iterator to that of
+ /// another.
+ #[inline]
+ fn cmp<I>(mut self, other: I) -> Result<Ordering, Self::Error>
+ where
+ Self: Sized,
+ I: IntoFallibleIterator<Item = Self::Item, Error = Self::Error>,
+ Self::Item: Ord,
+ {
+ let mut other = other.into_fallible_iter();
+
+ loop {
+ match (self.next()?, other.next()?) {
+ (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),
+ },
+ }
+ }
+ }
+
+ /// Lexicographically compares the elements of this iterator to that of
+ /// another.
+ #[inline]
+ fn partial_cmp<I>(mut self, other: I) -> Result<Option<Ordering>, Self::Error>
+ where
+ Self: Sized,
+ I: IntoFallibleIterator<Error = Self::Error>,
+ Self::Item: PartialOrd<I::Item>,
+ {
+ let mut other = other.into_fallible_iter();
+
+ loop {
+ match (self.next()?, other.next()?) {
+ (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),
+ },
+ }
+ }
+ }
+
+ /// Determines if the elements of this iterator are equal to those of
+ /// another.
+ #[inline]
+ fn eq<I>(mut self, other: I) -> Result<bool, Self::Error>
+ where
+ Self: Sized,
+ I: IntoFallibleIterator<Error = Self::Error>,
+ Self::Item: PartialEq<I::Item>,
+ {
+ let mut other = other.into_fallible_iter();
+
+ loop {
+ match (self.next()?, other.next()?) {
+ (None, None) => return Ok(true),
+ (None, _) | (_, None) => return Ok(false),
+ (Some(x), Some(y)) => {
+ if x != y {
+ return Ok(false);
+ }
+ }
+ }
+ }
+ }
+
+ /// Determines if the elements of this iterator are not equal to those of
+ /// another.
+ #[inline]
+ fn ne<I>(mut self, other: I) -> Result<bool, Self::Error>
+ where
+ Self: Sized,
+ I: IntoFallibleIterator<Error = Self::Error>,
+ Self::Item: PartialEq<I::Item>,
+ {
+ let mut other = other.into_fallible_iter();
+
+ loop {
+ match (self.next()?, other.next()?) {
+ (None, None) => return Ok(false),
+ (None, _) | (_, None) => return Ok(true),
+ (Some(x), Some(y)) => {
+ if x != y {
+ return Ok(true);
+ }
+ }
+ }
+ }
+ }
+
+ /// Determines if the elements of this iterator are lexicographically less
+ /// than those of another.
+ #[inline]
+ fn lt<I>(mut self, other: I) -> Result<bool, Self::Error>
+ where
+ Self: Sized,
+ I: IntoFallibleIterator<Error = Self::Error>,
+ Self::Item: PartialOrd<I::Item>,
+ {
+ let mut other = other.into_fallible_iter();
+
+ loop {
+ match (self.next()?, other.next()?) {
+ (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),
+ },
+ }
+ }
+ }
+
+ /// Determines if the elements of this iterator are lexicographically less
+ /// than or equal to those of another.
+ #[inline]
+ fn le<I>(mut self, other: I) -> Result<bool, Self::Error>
+ where
+ Self: Sized,
+ I: IntoFallibleIterator<Error = Self::Error>,
+ Self::Item: PartialOrd<I::Item>,
+ {
+ let mut other = other.into_fallible_iter();
+
+ loop {
+ match (self.next()?, other.next()?) {
+ (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),
+ },
+ }
+ }
+ }
+
+ /// Determines if the elements of this iterator are lexicographically
+ /// greater than those of another.
+ #[inline]
+ fn gt<I>(mut self, other: I) -> Result<bool, Self::Error>
+ where
+ Self: Sized,
+ I: IntoFallibleIterator<Error = Self::Error>,
+ Self::Item: PartialOrd<I::Item>,
+ {
+ let mut other = other.into_fallible_iter();
+
+ loop {
+ match (self.next()?, other.next()?) {
+ (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),
+ },
+ }
+ }
+ }
+
+ /// Determines if the elements of this iterator are lexicographically
+ /// greater than or equal to those of another.
+ #[inline]
+ fn ge<I>(mut self, other: I) -> Result<bool, Self::Error>
+ where
+ Self: Sized,
+ I: IntoFallibleIterator<Error = Self::Error>,
+ Self::Item: PartialOrd<I::Item>,
+ {
+ let mut other = other.into_fallible_iter();
+
+ loop {
+ match (self.next()?, other.next()?) {
+ (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),
+ },
+ }
+ }
+ }
+
+ /// Returns a normal (non-fallible) iterator over `Result<Item, Error>`.
+ #[inline]
+ fn iterator(self) -> Iterator<Self>
+ where
+ Self: Sized,
+ {
+ Iterator(self)
+ }
+
+ /// Returns an iterator which applies a transform to the errors of the
+ /// underlying iterator.
+ #[inline]
+ fn map_err<B, F>(self, f: F) -> MapErr<Self, F>
+ where
+ F: FnMut(Self::Error) -> B,
+ Self: Sized,
+ {
+ MapErr { it: self, f: f }
+ }
+}
+
+impl<I: FallibleIterator + ?Sized> FallibleIterator for &mut I {
+ type Item = I::Item;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, I::Error> {
+ (**self).next()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (**self).size_hint()
+ }
+
+ #[inline]
+ fn nth(&mut self, n: usize) -> Result<Option<I::Item>, I::Error> {
+ (**self).nth(n)
+ }
+}
+
+impl<I: DoubleEndedFallibleIterator + ?Sized> DoubleEndedFallibleIterator for &mut I {
+ #[inline]
+ fn next_back(&mut self) -> Result<Option<I::Item>, I::Error> {
+ (**self).next_back()
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<I: FallibleIterator + ?Sized> FallibleIterator for Box<I> {
+ type Item = I::Item;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, I::Error> {
+ (**self).next()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (**self).size_hint()
+ }
+
+ #[inline]
+ fn nth(&mut self, n: usize) -> Result<Option<I::Item>, I::Error> {
+ (**self).nth(n)
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<I: DoubleEndedFallibleIterator + ?Sized> DoubleEndedFallibleIterator for Box<I> {
+ #[inline]
+ fn next_back(&mut self) -> Result<Option<I::Item>, I::Error> {
+ (**self).next_back()
+ }
+}
+
+/// A fallible iterator able to yield elements from both ends.
+pub trait DoubleEndedFallibleIterator: FallibleIterator {
+ /// Advances the end of the iterator, returning the last value.
+ fn next_back(&mut self) -> Result<Option<Self::Item>, Self::Error>;
+
+ /// Applies a function over the elements of the iterator in reverse order, producing a single final value.
+ #[inline]
+ fn rfold<B, F>(mut self, init: B, f: F) -> Result<B, Self::Error>
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> Result<B, Self::Error>,
+ {
+ 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<B, E, F>(&mut self, mut init: B, mut f: F) -> Result<B, E>
+ where
+ Self: Sized,
+ E: From<Self::Error>,
+ F: FnMut(B, Self::Item) -> Result<B, E>,
+ {
+ while let Some(v) = self.next_back()? {
+ init = f(init, v)?;
+ }
+ Ok(init)
+ }
+}
+
+/// Conversion from a fallible iterator.
+pub trait FromFallibleIterator<T>: Sized {
+ /// Creates a value from a fallible iterator.
+ fn from_fallible_iter<I>(it: I) -> Result<Self, I::Error>
+ where
+ I: IntoFallibleIterator<Item = T>;
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<T> FromFallibleIterator<T> for Vec<T> {
+ #[inline]
+ fn from_fallible_iter<I>(it: I) -> Result<Vec<T>, I::Error>
+ where
+ I: IntoFallibleIterator<Item = T>,
+ {
+ let it = it.into_fallible_iter();
+ let mut vec = Vec::with_capacity(it.size_hint().0);
+ it.for_each(|v| Ok(vec.push(v)))?;
+ Ok(vec)
+ }
+}
+
+#[cfg(feature = "std")]
+impl<T, S> FromFallibleIterator<T> for HashSet<T, S>
+where
+ T: Hash + Eq,
+ S: BuildHasher + Default,
+{
+ #[inline]
+ fn from_fallible_iter<I>(it: I) -> Result<HashSet<T, S>, I::Error>
+ where
+ I: IntoFallibleIterator<Item = T>,
+ {
+ let it = it.into_fallible_iter();
+ let mut set = HashSet::default();
+ set.reserve(it.size_hint().0);
+ it.for_each(|v| {
+ set.insert(v);
+ Ok(())
+ })?;
+ Ok(set)
+ }
+}
+
+#[cfg(feature = "std")]
+impl<K, V, S> FromFallibleIterator<(K, V)> for HashMap<K, V, S>
+where
+ K: Hash + Eq,
+ S: BuildHasher + Default,
+{
+ #[inline]
+ fn from_fallible_iter<I>(it: I) -> Result<HashMap<K, V, S>, I::Error>
+ where
+ I: IntoFallibleIterator<Item = (K, V)>,
+ {
+ let it = it.into_fallible_iter();
+ let mut map = HashMap::default();
+ map.reserve(it.size_hint().0);
+ it.for_each(|(k, v)| {
+ map.insert(k, v);
+ Ok(())
+ })?;
+ Ok(map)
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<T> FromFallibleIterator<T> for BTreeSet<T>
+where
+ T: Ord,
+{
+ #[inline]
+ fn from_fallible_iter<I>(it: I) -> Result<BTreeSet<T>, I::Error>
+ where
+ I: IntoFallibleIterator<Item = T>,
+ {
+ let it = it.into_fallible_iter();
+ let mut set = BTreeSet::new();
+ it.for_each(|v| {
+ set.insert(v);
+ Ok(())
+ })?;
+ Ok(set)
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<K, V> FromFallibleIterator<(K, V)> for BTreeMap<K, V>
+where
+ K: Ord,
+{
+ #[inline]
+ fn from_fallible_iter<I>(it: I) -> Result<BTreeMap<K, V>, I::Error>
+ where
+ I: IntoFallibleIterator<Item = (K, V)>,
+ {
+ let it = it.into_fallible_iter();
+ let mut map = BTreeMap::new();
+ it.for_each(|(k, v)| {
+ map.insert(k, v);
+ Ok(())
+ })?;
+ Ok(map)
+ }
+}
+
+/// Conversion into a `FallibleIterator`.
+pub trait IntoFallibleIterator {
+ /// The elements of the iterator.
+ type Item;
+
+ /// The error value of the iterator.
+ type Error;
+
+ /// The iterator.
+ type IntoFallibleIter: FallibleIterator<Item = Self::Item, Error = Self::Error>;
+
+ /// Creates a fallible iterator from a value.
+ fn into_fallible_iter(self) -> Self::IntoFallibleIter;
+}
+
+impl<I> IntoFallibleIterator for I
+where
+ I: FallibleIterator,
+{
+ type Item = I::Item;
+ type Error = I::Error;
+ type IntoFallibleIter = I;
+
+ #[inline]
+ fn into_fallible_iter(self) -> I {
+ self
+ }
+}
+
+/// An iterator which applies a fallible transform to the elements of the
+/// underlying iterator.
+#[derive(Clone, Debug)]
+pub struct Map<T, F> {
+ it: T,
+ f: F,
+}
+
+impl<T, F, B> FallibleIterator for Map<T, F>
+where
+ T: FallibleIterator,
+ F: FnMut(T::Item) -> Result<B, T::Error>,
+{
+ type Item = B;
+ type Error = T::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<B>, T::Error> {
+ match self.it.next() {
+ Ok(Some(v)) => Ok(Some((self.f)(v)?)),
+ Ok(None) => Ok(None),
+ Err(e) => Err(e),
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.it.size_hint()
+ }
+
+ #[inline]
+ fn try_fold<C, E, G>(&mut self, init: C, mut f: G) -> Result<C, E>
+ where
+ E: From<T::Error>,
+ G: FnMut(C, B) -> Result<C, E>,
+ {
+ let map = &mut self.f;
+ self.it.try_fold(init, |b, v| f(b, map(v)?))
+ }
+}
+
+impl<B, F, I> DoubleEndedFallibleIterator for Map<I, F>
+where
+ I: DoubleEndedFallibleIterator,
+ F: FnMut(I::Item) -> Result<B, I::Error>,
+{
+ #[inline]
+ fn next_back(&mut self) -> Result<Option<B>, I::Error> {
+ match self.it.next_back() {
+ Ok(Some(v)) => Ok(Some((self.f)(v)?)),
+ Ok(None) => Ok(None),
+ Err(e) => Err(e),
+ }
+ }
+
+ #[inline]
+ fn try_rfold<C, E, G>(&mut self, init: C, mut f: G) -> Result<C, E>
+ where
+ E: From<I::Error>,
+ G: FnMut(C, B) -> Result<C, E>,
+ {
+ let map = &mut self.f;
+ self.it.try_rfold(init, |acc, v| f(acc, map(v)?))
+ }
+}
+
+#[derive(Clone, Debug)]
+enum ChainState {
+ Both,
+ Front,
+ Back,
+}
+
+/// An iterator which yields the elements of one iterator followed by another.
+#[derive(Clone, Debug)]
+pub struct Chain<T, U> {
+ front: T,
+ back: U,
+ state: ChainState,
+}
+
+impl<T, U> FallibleIterator for Chain<T, U>
+where
+ T: FallibleIterator,
+ U: FallibleIterator<Item = T::Item, Error = T::Error>,
+{
+ type Item = T::Item;
+ type Error = T::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<T::Item>, T::Error> {
+ match self.state {
+ ChainState::Both => match 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(),
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let front_hint = self.front.size_hint();
+ let back_hint = self.back.size_hint();
+
+ let low = front_hint.0.saturating_add(back_hint.0);
+ let high = match (front_hint.1, back_hint.1) {
+ (Some(f), Some(b)) => f.checked_add(b),
+ _ => None,
+ };
+
+ (low, high)
+ }
+
+ #[inline]
+ fn count(self) -> Result<usize, T::Error> {
+ match self.state {
+ ChainState::Both => Ok(self.front.count()? + self.back.count()?),
+ ChainState::Front => self.front.count(),
+ ChainState::Back => self.back.count(),
+ }
+ }
+
+ #[inline]
+ fn try_fold<B, E, F>(&mut self, init: B, mut f: F) -> Result<B, E>
+ where
+ E: From<T::Error>,
+ F: FnMut(B, T::Item) -> Result<B, E>,
+ {
+ match self.state {
+ ChainState::Both => {
+ let init = self.front.try_fold(init, &mut f)?;
+ self.state = ChainState::Back;
+ self.back.try_fold(init, f)
+ }
+ ChainState::Front => self.front.try_fold(init, f),
+ ChainState::Back => self.back.try_fold(init, f),
+ }
+ }
+
+ #[inline]
+ fn find<F>(&mut self, mut f: F) -> Result<Option<T::Item>, T::Error>
+ where
+ F: FnMut(&T::Item) -> Result<bool, T::Error>,
+ {
+ 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<Option<T::Item>, T::Error> {
+ match self.state {
+ ChainState::Both => {
+ self.front.last()?;
+ self.back.last()
+ }
+ ChainState::Front => self.front.last(),
+ ChainState::Back => self.back.last(),
+ }
+ }
+}
+
+impl<T, U> DoubleEndedFallibleIterator for Chain<T, U>
+where
+ T: DoubleEndedFallibleIterator,
+ U: DoubleEndedFallibleIterator<Item = T::Item, Error = T::Error>,
+{
+ #[inline]
+ fn next_back(&mut self) -> Result<Option<T::Item>, T::Error> {
+ match self.state {
+ ChainState::Both => match 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(),
+ }
+ }
+
+ #[inline]
+ fn try_rfold<B, E, F>(&mut self, init: B, mut f: F) -> Result<B, E>
+ where
+ E: From<T::Error>,
+ F: FnMut(B, T::Item) -> Result<B, E>,
+ {
+ match self.state {
+ ChainState::Both => {
+ let init = self.back.try_rfold(init, &mut f)?;
+ self.state = ChainState::Front;
+ self.front.try_rfold(init, f)
+ }
+ ChainState::Front => self.front.try_rfold(init, f),
+ ChainState::Back => self.back.try_rfold(init, f),
+ }
+ }
+}
+
+/// An iterator which clones the elements of the underlying iterator.
+#[derive(Clone, Debug)]
+pub struct Cloned<I>(I);
+
+impl<'a, T, I> FallibleIterator for Cloned<I>
+where
+ I: FallibleIterator<Item = &'a T>,
+ T: 'a + Clone,
+{
+ type Item = T;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<T>, I::Error> {
+ self.0.next().map(|o| o.cloned())
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.0.size_hint()
+ }
+
+ #[inline]
+ fn try_fold<B, E, F>(&mut self, init: B, mut f: F) -> Result<B, E>
+ where
+ E: From<I::Error>,
+ F: FnMut(B, T) -> Result<B, E>,
+ {
+ self.0.try_fold(init, |acc, v| f(acc, v.clone()))
+ }
+}
+
+impl<'a, T, I> DoubleEndedFallibleIterator for Cloned<I>
+where
+ I: DoubleEndedFallibleIterator<Item = &'a T>,
+ T: 'a + Clone,
+{
+ #[inline]
+ fn next_back(&mut self) -> Result<Option<T>, I::Error> {
+ self.0.next_back().map(|o| o.cloned())
+ }
+
+ #[inline]
+ fn try_rfold<B, E, F>(&mut self, init: B, mut f: F) -> Result<B, E>
+ where
+ E: From<I::Error>,
+ F: FnMut(B, T) -> Result<B, E>,
+ {
+ self.0.try_rfold(init, |acc, v| f(acc, v.clone()))
+ }
+}
+
+/// Converts an `Iterator<Item = Result<T, E>>` into a `FallibleIterator<Item = T, Error = E>`.
+#[inline]
+pub fn convert<T, E, I>(it: I) -> Convert<I>
+where
+ I: iter::Iterator<Item = Result<T, E>>,
+{
+ Convert(it)
+}
+
+/// A fallible iterator that wraps a normal iterator over `Result`s.
+#[derive(Clone, Debug)]
+pub struct Convert<I>(I);
+
+impl<T, E, I> FallibleIterator for Convert<I>
+where
+ I: iter::Iterator<Item = Result<T, E>>,
+{
+ type Item = T;
+ type Error = E;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<T>, E> {
+ match self.0.next() {
+ Some(Ok(i)) => Ok(Some(i)),
+ Some(Err(e)) => Err(e),
+ None => Ok(None),
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.0.size_hint()
+ }
+
+ #[inline]
+ fn try_fold<B, E2, F>(&mut self, init: B, mut f: F) -> Result<B, E2>
+ where
+ E2: From<E>,
+ F: FnMut(B, T) -> Result<B, E2>,
+ {
+ self.0.try_fold(init, |acc, v| f(acc, v?))
+ }
+}
+
+impl<T, E, I> DoubleEndedFallibleIterator for Convert<I>
+where
+ I: DoubleEndedIterator<Item = Result<T, E>>,
+{
+ #[inline]
+ fn next_back(&mut self) -> Result<Option<T>, E> {
+ match self.0.next_back() {
+ Some(Ok(i)) => Ok(Some(i)),
+ Some(Err(e)) => Err(e),
+ None => Ok(None),
+ }
+ }
+
+ #[inline]
+ fn try_rfold<B, E2, F>(&mut self, init: B, mut f: F) -> Result<B, E2>
+ where
+ E2: From<E>,
+ F: FnMut(B, T) -> Result<B, E2>,
+ {
+ self.0.try_rfold(init, |acc, v| f(acc, v?))
+ }
+}
+
+/// An iterator that yields the iteration count as well as the values of the
+/// underlying iterator.
+#[derive(Clone, Debug)]
+pub struct Enumerate<I> {
+ it: I,
+ n: usize,
+}
+
+impl<I> FallibleIterator for Enumerate<I>
+where
+ I: FallibleIterator,
+{
+ type Item = (usize, I::Item);
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<(usize, I::Item)>, I::Error> {
+ self.it.next().map(|o| {
+ o.map(|e| {
+ let i = self.n;
+ self.n += 1;
+ (i, e)
+ })
+ })
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.it.size_hint()
+ }
+
+ #[inline]
+ fn count(self) -> Result<usize, I::Error> {
+ self.it.count()
+ }
+
+ #[inline]
+ fn nth(&mut self, n: usize) -> Result<Option<(usize, I::Item)>, 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 try_fold<B, E, F>(&mut self, init: B, mut f: F) -> Result<B, E>
+ where
+ E: From<I::Error>,
+ F: FnMut(B, (usize, I::Item)) -> Result<B, E>,
+ {
+ let n = &mut self.n;
+ self.it.try_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
+/// underlying iterator should be yielded.
+#[derive(Clone, Debug)]
+pub struct Filter<I, F> {
+ it: I,
+ f: F,
+}
+
+impl<I, F> FallibleIterator for Filter<I, F>
+where
+ I: FallibleIterator,
+ F: FnMut(&I::Item) -> Result<bool, I::Error>,
+{
+ type Item = I::Item;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, I::Error> {
+ 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]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (0, self.it.size_hint().1)
+ }
+
+ #[inline]
+ fn try_fold<B, E, G>(&mut self, init: B, mut f: G) -> Result<B, E>
+ where
+ E: From<I::Error>,
+ G: FnMut(B, I::Item) -> Result<B, E>,
+ {
+ let predicate = &mut self.f;
+ self.it.try_fold(
+ init,
+ |acc, v| {
+ if predicate(&v)? {
+ f(acc, v)
+ } else {
+ Ok(acc)
+ }
+ },
+ )
+ }
+}
+
+impl<I, F> DoubleEndedFallibleIterator for Filter<I, F>
+where
+ I: DoubleEndedFallibleIterator,
+ F: FnMut(&I::Item) -> Result<bool, I::Error>,
+{
+ #[inline]
+ fn next_back(&mut self) -> Result<Option<I::Item>, I::Error> {
+ 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 try_rfold<B, E, G>(&mut self, init: B, mut f: G) -> Result<B, E>
+ where
+ E: From<I::Error>,
+ G: FnMut(B, I::Item) -> Result<B, E>,
+ {
+ let predicate = &mut self.f;
+ self.it.try_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
+/// iterator.
+#[derive(Clone, Debug)]
+pub struct FilterMap<I, F> {
+ it: I,
+ f: F,
+}
+
+impl<B, I, F> FallibleIterator for FilterMap<I, F>
+where
+ I: FallibleIterator,
+ F: FnMut(I::Item) -> Result<Option<B>, I::Error>,
+{
+ type Item = B;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<B>, I::Error> {
+ 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]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (0, self.it.size_hint().1)
+ }
+
+ #[inline]
+ fn try_fold<C, E, G>(&mut self, init: C, mut f: G) -> Result<C, E>
+ where
+ E: From<I::Error>,
+ G: FnMut(C, B) -> Result<C, E>,
+ {
+ let map = &mut self.f;
+ self.it.try_fold(init, |acc, v| match map(v)? {
+ Some(v) => f(acc, v),
+ None => Ok(acc),
+ })
+ }
+}
+
+impl<B, I, F> DoubleEndedFallibleIterator for FilterMap<I, F>
+where
+ I: DoubleEndedFallibleIterator,
+ F: FnMut(I::Item) -> Result<Option<B>, I::Error>,
+{
+ #[inline]
+ fn next_back(&mut self) -> Result<Option<B>, I::Error> {
+ 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 try_rfold<C, E, G>(&mut self, init: C, mut f: G) -> Result<C, E>
+ where
+ E: From<I::Error>,
+ G: FnMut(C, B) -> Result<C, E>,
+ {
+ let map = &mut self.f;
+ self.it.try_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.
+#[derive(Clone, Debug)]
+pub struct FlatMap<I, U, F>
+where
+ U: IntoFallibleIterator,
+{
+ it: Map<I, F>,
+ cur: Option<U::IntoFallibleIter>,
+}
+
+impl<I, U, F> FallibleIterator for FlatMap<I, U, F>
+where
+ I: FallibleIterator,
+ U: IntoFallibleIterator<Error = I::Error>,
+ F: FnMut(I::Item) -> Result<U, I::Error>,
+{
+ type Item = U::Item;
+ type Error = U::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<U::Item>, 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_iter()),
+ None => return Ok(None),
+ }
+ }
+ }
+
+ #[inline]
+ fn try_fold<B, E, G>(&mut self, init: B, mut f: G) -> Result<B, E>
+ where
+ E: From<U::Error>,
+ G: FnMut(B, U::Item) -> Result<B, E>,
+ {
+ 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)
+ }
+ }
+ })
+ }
+}
+
+/// An iterator which flattens an iterator of iterators, yielding those iterators' elements.
+pub struct Flatten<I>
+where
+ I: FallibleIterator,
+ I::Item: IntoFallibleIterator,
+{
+ it: I,
+ cur: Option<<I::Item as IntoFallibleIterator>::IntoFallibleIter>,
+}
+
+impl<I> Clone for Flatten<I>
+where
+ I: FallibleIterator + Clone,
+ I::Item: IntoFallibleIterator,
+ <I::Item as IntoFallibleIterator>::IntoFallibleIter: Clone,
+{
+ #[inline]
+ fn clone(&self) -> Flatten<I> {
+ Flatten {
+ it: self.it.clone(),
+ cur: self.cur.clone(),
+ }
+ }
+}
+
+impl<I> FallibleIterator for Flatten<I>
+where
+ I: FallibleIterator,
+ I::Item: IntoFallibleIterator<Error = I::Error>,
+{
+ type Item = <I::Item as IntoFallibleIterator>::Item;
+ type Error = <I::Item as IntoFallibleIterator>::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<Self::Item>, 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_iter()),
+ None => return Ok(None),
+ }
+ }
+ }
+
+ #[inline]
+ fn try_fold<B, E, G>(&mut self, init: B, mut f: G) -> Result<B, E>
+ where
+ E: From<Self::Error>,
+ G: FnMut(B, Self::Item) -> Result<B, E>,
+ {
+ 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)
+ }
+ }
+ })
+ }
+}
+
+/// An iterator that yields `Ok(None)` forever after the underlying iterator
+/// yields `Ok(None)` once.
+#[derive(Clone, Debug)]
+pub struct Fuse<I> {
+ it: I,
+ done: bool,
+}
+
+impl<I> FallibleIterator for Fuse<I>
+where
+ I: FallibleIterator,
+{
+ type Item = I::Item;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, I::Error> {
+ if self.done {
+ return Ok(None);
+ }
+
+ match self.it.next()? {
+ Some(i) => Ok(Some(i)),
+ None => {
+ self.done = true;
+ Ok(None)
+ }
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ if self.done {
+ (0, Some(0))
+ } else {
+ self.it.size_hint()
+ }
+ }
+
+ #[inline]
+ fn count(self) -> Result<usize, I::Error> {
+ if self.done {
+ Ok(0)
+ } else {
+ self.it.count()
+ }
+ }
+
+ #[inline]
+ fn last(self) -> Result<Option<I::Item>, I::Error> {
+ if self.done {
+ Ok(None)
+ } else {
+ self.it.last()
+ }
+ }
+
+ #[inline]
+ fn nth(&mut self, n: usize) -> Result<Option<I::Item>, 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 try_fold<B, E, F>(&mut self, init: B, f: F) -> Result<B, E>
+ where
+ E: From<I::Error>,
+ F: FnMut(B, I::Item) -> Result<B, E>,
+ {
+ if self.done {
+ Ok(init)
+ } else {
+ self.it.try_fold(init, f)
+ }
+ }
+}
+
+/// An iterator which passes each element to a closure before returning it.
+#[derive(Clone, Debug)]
+pub struct Inspect<I, F> {
+ it: I,
+ f: F,
+}
+
+impl<I, F> FallibleIterator for Inspect<I, F>
+where
+ I: FallibleIterator,
+ F: FnMut(&I::Item) -> Result<(), I::Error>,
+{
+ type Item = I::Item;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, I::Error> {
+ match self.it.next()? {
+ Some(i) => {
+ (self.f)(&i)?;
+ Ok(Some(i))
+ }
+ None => Ok(None),
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.it.size_hint()
+ }
+
+ #[inline]
+ fn try_fold<B, E, G>(&mut self, init: B, mut f: G) -> Result<B, E>
+ where
+ E: From<I::Error>,
+ G: FnMut(B, I::Item) -> Result<B, E>,
+ {
+ let inspect = &mut self.f;
+ self.it.try_fold(init, |acc, v| {
+ inspect(&v)?;
+ f(acc, v)
+ })
+ }
+}
+
+impl<I, F> DoubleEndedFallibleIterator for Inspect<I, F>
+where
+ I: DoubleEndedFallibleIterator,
+ F: FnMut(&I::Item) -> Result<(), I::Error>,
+{
+ #[inline]
+ fn next_back(&mut self) -> Result<Option<I::Item>, I::Error> {
+ match self.it.next_back()? {
+ Some(i) => {
+ (self.f)(&i)?;
+ Ok(Some(i))
+ }
+ None => Ok(None),
+ }
+ }
+
+ #[inline]
+ fn try_rfold<B, E, G>(&mut self, init: B, mut f: G) -> Result<B, E>
+ where
+ E: From<I::Error>,
+ G: FnMut(B, I::Item) -> Result<B, E>,
+ {
+ let inspect = &mut self.f;
+ self.it.try_rfold(init, |acc, v| {
+ inspect(&v)?;
+ f(acc, v)
+ })
+ }
+}
+
+/// A normal (non-fallible) iterator which wraps a fallible iterator.
+#[derive(Clone, Debug)]
+pub struct Iterator<I>(I);
+
+impl<I> iter::Iterator for Iterator<I>
+where
+ I: FallibleIterator,
+{
+ type Item = Result<I::Item, I::Error>;
+
+ #[inline]
+ fn next(&mut self) -> Option<Result<I::Item, I::Error>> {
+ match self.0.next() {
+ Ok(Some(v)) => Some(Ok(v)),
+ Ok(None) => None,
+ Err(e) => Some(Err(e)),
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.0.size_hint()
+ }
+}
+
+impl<I> DoubleEndedIterator for Iterator<I>
+where
+ I: DoubleEndedFallibleIterator,
+{
+ #[inline]
+ fn next_back(&mut self) -> Option<Result<I::Item, I::Error>> {
+ match self.0.next_back() {
+ Ok(Some(v)) => Some(Ok(v)),
+ Ok(None) => None,
+ Err(e) => Some(Err(e)),
+ }
+ }
+}
+
+/// An iterator which applies a transform to the errors of the underlying
+/// iterator.
+#[derive(Clone, Debug)]
+pub struct MapErr<I, F> {
+ it: I,
+ f: F,
+}
+
+impl<B, F, I> FallibleIterator for MapErr<I, F>
+where
+ I: FallibleIterator,
+ F: FnMut(I::Error) -> B,
+{
+ type Item = I::Item;
+ type Error = B;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, B> {
+ self.it.next().map_err(&mut self.f)
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.it.size_hint()
+ }
+
+ #[inline]
+ fn count(mut self) -> Result<usize, B> {
+ self.it.count().map_err(&mut self.f)
+ }
+
+ #[inline]
+ fn last(mut self) -> Result<Option<I::Item>, B> {
+ self.it.last().map_err(&mut self.f)
+ }
+
+ #[inline]
+ fn nth(&mut self, n: usize) -> Result<Option<I::Item>, B> {
+ self.it.nth(n).map_err(&mut self.f)
+ }
+
+ #[inline]
+ fn try_fold<C, E, G>(&mut self, init: C, mut f: G) -> Result<C, E>
+ where
+ E: From<B>,
+ G: FnMut(C, I::Item) -> Result<C, E>,
+ {
+ 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<B, F, I> DoubleEndedFallibleIterator for MapErr<I, F>
+where
+ I: DoubleEndedFallibleIterator,
+ F: FnMut(I::Error) -> B,
+{
+ #[inline]
+ fn next_back(&mut self) -> Result<Option<I::Item>, B> {
+ self.it.next_back().map_err(&mut self.f)
+ }
+
+ #[inline]
+ fn try_rfold<C, E, G>(&mut self, init: C, mut f: G) -> Result<C, E>
+ where
+ E: From<B>,
+ G: FnMut(C, I::Item) -> Result<C, E>,
+ {
+ 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<T, U> {
+ It(T),
+ Fold(U),
+}
+
+impl<T, U> From<T> for MappedErr<T, U> {
+ #[inline]
+ fn from(t: T) -> MappedErr<T, U> {
+ MappedErr::It(t)
+ }
+}
+
+/// An iterator which can look at the next element without consuming it.
+#[derive(Clone, Debug)]
+pub struct Peekable<I: FallibleIterator> {
+ it: I,
+ next: Option<I::Item>,
+}
+
+impl<I> Peekable<I>
+where
+ I: FallibleIterator,
+{
+ /// Returns a reference to the next value without advancing the iterator.
+ #[inline]
+ pub fn peek(&mut self) -> Result<Option<&I::Item>, I::Error> {
+ if self.next.is_none() {
+ self.next = self.it.next()?;
+ }
+
+ Ok(self.next.as_ref())
+ }
+}
+
+impl<I> FallibleIterator for Peekable<I>
+where
+ I: FallibleIterator,
+{
+ type Item = I::Item;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, I::Error> {
+ if let Some(next) = self.next.take() {
+ return Ok(Some(next));
+ }
+
+ self.it.next()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let mut hint = self.it.size_hint();
+ if self.next.is_some() {
+ hint.0 = hint.0.saturating_add(1);
+ hint.1 = hint.1.and_then(|h| h.checked_add(1));
+ }
+ hint
+ }
+
+ #[inline]
+ fn try_fold<B, E, F>(&mut self, init: B, mut f: F) -> Result<B, E>
+ where
+ E: From<I::Error>,
+ F: FnMut(B, I::Item) -> Result<B, E>,
+ {
+ 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
+/// order.
+#[derive(Clone, Debug)]
+pub struct Rev<I>(I);
+
+impl<I> FallibleIterator for Rev<I>
+where
+ I: DoubleEndedFallibleIterator,
+{
+ type Item = I::Item;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, I::Error> {
+ self.0.next_back()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.0.size_hint()
+ }
+
+ #[inline]
+ fn count(self) -> Result<usize, I::Error> {
+ self.0.count()
+ }
+
+ #[inline]
+ fn try_fold<B, E, F>(&mut self, init: B, f: F) -> Result<B, E>
+ where
+ E: From<I::Error>,
+ F: FnMut(B, I::Item) -> Result<B, E>,
+ {
+ self.0.try_rfold(init, f)
+ }
+}
+
+impl<I> DoubleEndedFallibleIterator for Rev<I>
+where
+ I: DoubleEndedFallibleIterator,
+{
+ #[inline]
+ fn next_back(&mut self) -> Result<Option<I::Item>, I::Error> {
+ self.0.next()
+ }
+
+ #[inline]
+ fn try_rfold<B, E, F>(&mut self, init: B, f: F) -> Result<B, E>
+ where
+ E: From<I::Error>,
+ F: FnMut(B, I::Item) -> Result<B, E>,
+ {
+ self.0.try_fold(init, f)
+ }
+}
+
+/// An iterator which applies a stateful closure.
+#[derive(Clone, Debug)]
+pub struct Scan<I, St, F> {
+ it: I,
+ f: F,
+ state: St,
+}
+
+impl<B, I, St, F> FallibleIterator for Scan<I, St, F>
+where
+ I: FallibleIterator,
+ F: FnMut(&mut St, I::Item) -> Result<Option<B>, I::Error>,
+{
+ type Item = B;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<B>, I::Error> {
+ match self.it.next()? {
+ Some(v) => (self.f)(&mut self.state, v),
+ None => Ok(None),
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let hint = self.it.size_hint();
+ (0, hint.1)
+ }
+}
+
+/// An iterator which skips initial elements.
+#[derive(Clone, Debug)]
+pub struct Skip<I> {
+ it: I,
+ n: usize,
+}
+
+impl<I> FallibleIterator for Skip<I>
+where
+ I: FallibleIterator,
+{
+ type Item = I::Item;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, 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<usize>) {
+ 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<I, P> {
+ it: I,
+ flag: bool,
+ predicate: P,
+}
+
+impl<I, P> FallibleIterator for SkipWhile<I, P>
+where
+ I: FallibleIterator,
+ P: FnMut(&I::Item) -> Result<bool, I::Error>,
+{
+ type Item = I::Item;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, 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<usize>) {
+ 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<I> {
+ it: I,
+ step: usize,
+ first_take: bool,
+}
+
+impl<I> FallibleIterator for StepBy<I>
+where
+ I: FallibleIterator,
+{
+ type Item = I::Item;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, 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<usize>) {
+ 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)]
+pub struct Take<I> {
+ it: I,
+ remaining: usize,
+}
+
+impl<I> FallibleIterator for Take<I>
+where
+ I: FallibleIterator,
+{
+ type Item = I::Item;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, I::Error> {
+ if self.remaining == 0 {
+ return Ok(None);
+ }
+
+ let next = self.it.next();
+ if let Ok(Some(_)) = next {
+ self.remaining -= 1;
+ }
+ next
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let hint = self.it.size_hint();
+ (
+ cmp::min(hint.0, self.remaining),
+ hint.1.map(|n| cmp::min(n, self.remaining)),
+ )
+ }
+}
+
+/// An iterator which yields elements based on a predicate.
+#[derive(Clone, Debug)]
+pub struct TakeWhile<I, P> {
+ it: I,
+ flag: bool,
+ predicate: P,
+}
+
+impl<I, P> FallibleIterator for TakeWhile<I, P>
+where
+ I: FallibleIterator,
+ P: FnMut(&I::Item) -> Result<bool, I::Error>,
+{
+ type Item = I::Item;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, 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<usize>) {
+ if self.flag {
+ (0, Some(0))
+ } else {
+ let hint = self.it.size_hint();
+ (0, hint.1)
+ }
+ }
+}
+
+/// An iterator which cycles another endlessly.
+#[derive(Clone, Debug)]
+pub struct Cycle<I> {
+ it: I,
+ cur: I,
+}
+
+impl<I> FallibleIterator for Cycle<I>
+where
+ I: FallibleIterator + Clone,
+{
+ type Item = I::Item;
+ type Error = I::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<I::Item>, 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>) {
+ (usize::max_value(), None)
+ }
+}
+
+/// An iterator that yields pairs of this iterator's and another iterator's
+/// values.
+#[derive(Clone, Debug)]
+pub struct Zip<T, U>(T, U);
+
+impl<T, U> FallibleIterator for Zip<T, U>
+where
+ T: FallibleIterator,
+ U: FallibleIterator<Error = T::Error>,
+{
+ type Item = (T::Item, U::Item);
+ type Error = T::Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<(T::Item, U::Item)>, T::Error> {
+ match (self.0.next()?, self.1.next()?) {
+ (Some(a), Some(b)) => Ok(Some((a, b))),
+ _ => Ok(None),
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let a = self.0.size_hint();
+ let b = self.1.size_hint();
+
+ let low = cmp::min(a.0, b.0);
+
+ let high = match (a.1, b.1) {
+ (Some(a), Some(b)) => Some(cmp::min(a, b)),
+ (Some(a), None) => Some(a),
+ (None, Some(b)) => Some(b),
+ (None, None) => None,
+ };
+
+ (low, high)
+ }
+}
+
+fn _is_object_safe(_: &dyn DoubleEndedFallibleIterator<Item = (), Error = ()>) {}
diff --git a/src/test.rs b/src/test.rs
new file mode 100644
index 0000000..f7627c4
--- /dev/null
+++ b/src/test.rs
@@ -0,0 +1,455 @@
+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());
+}
+
+#[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());
+}
+
+#[test]
+fn chain() {
+ let a = convert(vec![0, 1, 2, 3].into_iter().map(Ok::<u32, ()>));
+ let b = convert(vec![4, 5, 6, 7].into_iter().map(Ok::<u32, ()>));
+ let it = a.chain(b);
+
+ assert_eq!(it.collect::<Vec<_>>().unwrap(), [0, 1, 2, 3, 4, 5, 6, 7]);
+
+ let a = convert(vec![0, 1, 2, 3].into_iter().map(Ok::<u32, ()>));
+ let b = convert(vec![4, 5, 6, 7].into_iter().map(Ok::<u32, ()>));
+ let it = a.chain(b).rev();
+
+ assert_eq!(it.collect::<Vec<_>>().unwrap(), [7, 6, 5, 4, 3, 2, 1, 0]);
+}
+
+#[test]
+fn count() {
+ 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());
+}
+
+#[test]
+fn enumerate() {
+ let it = convert(vec![5, 6, 7, 8].into_iter().map(Ok::<u32, ()>)).enumerate();
+
+ assert_eq!(
+ it.collect::<Vec<_>>().unwrap(),
+ [(0, 5), (1, 6), (2, 7), (3, 8)]
+ );
+}
+
+#[test]
+fn filter() {
+ let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::<u32, u32>));
+ let it = it.filter(|&x| if x % 2 == 0 { Ok(x % 3 == 0) } else { Err(x) });
+
+ assert_eq!(it.clone().collect::<Vec<_>>(), Err(1));
+ assert_eq!(it.rev().collect::<Vec<_>>(), Err(3));
+
+ let it = convert(vec![0, 2, 4, 6].into_iter().map(Ok::<u32, u32>));
+ let it = it.filter(|&x| if x % 2 == 0 { Ok(x % 3 == 0) } else { Err(x) });
+
+ assert_eq!(it.clone().collect::<Vec<_>>(), Ok(vec![0, 6]));
+ assert_eq!(it.rev().collect::<Vec<_>>(), Ok(vec![6, 0]))
+}
+
+#[test]
+fn filter_map() {
+ fn twos_and_threes(x: u32) -> Result<Option<u32>, 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::<u32, u32>))
+ .filter_map(twos_and_threes);
+
+ assert_eq!(it.clone().collect::<Vec<_>>(), Err(1));
+ assert_eq!(it.rev().collect::<Vec<_>>(), Err(5));
+
+ let it =
+ convert(vec![0, 2, 3, 4, 6].into_iter().map(Ok::<u32, u32>)).filter_map(twos_and_threes);
+
+ assert_eq!(it.clone().collect::<Vec<_>>(), Ok(vec![10, 12, 14, 16]));
+ assert_eq!(it.rev().collect::<Vec<_>>(), Ok(vec![16, 14, 12, 10]));
+}
+
+#[test]
+fn find() {
+ let mut it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::<u32, u32>));
+
+ assert_eq!(it.find(|x| Ok(x % 2 == 1)), Ok(Some(1)));
+ assert_eq!(it.next(), Ok(Some(2)));
+
+ let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::<u32, u32>));
+ 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() {
+ fn add_smol(a: u32, b: u32) -> Result<u32, u32> {
+ if b <= 2 {
+ Ok(a + b)
+ } else {
+ Err(b)
+ }
+ }
+
+ let it = convert(vec![0, 1, 3, 2].into_iter().map(Ok::<u32, u32>));
+ assert_eq!(it.fold(0, add_smol), Err(3));
+
+ let it = convert(vec![0, 1, 2, 1].into_iter().map(Ok::<u32, u32>));
+ 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::<u32, ()>));
+
+ 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) }),
+ );
+
+ 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::<u32, ()>));
+ assert_eq!(it.last().unwrap(), Some(3));
+}
+
+#[test]
+fn map() {
+ let it = convert(vec![0, 1, 2, 3, 4].into_iter().map(Ok::<u32, ()>)).map(|n| Ok(n * 2));
+ assert_eq!(it.clone().collect::<Vec<_>>().unwrap(), [0, 2, 4, 6, 8]);
+ assert_eq!(it.rev().collect::<Vec<_>>().unwrap(), [8, 6, 4, 2, 0]);
+
+ let it = convert(vec![0, 1, 2, 3, 4].into_iter().map(Ok::<u32, ()>)).map(|n| {
+ if n == 2 {
+ Err(())
+ } else {
+ Ok(n * 2)
+ }
+ });
+
+ {
+ 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]
+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::<Vec<_>>(), Err(1));
+ assert_eq!(it.rev().collect::<Vec<_>>(), Err(3));
+}
+
+#[test]
+fn max() {
+ let it = convert(vec![0, 3, 1, -10].into_iter().map(Ok::<i32, ()>));
+ assert_eq!(it.max().unwrap(), Some(3));
+}
+
+#[test]
+fn max_by_key() {
+ let it = convert(vec![0, 3, 1, -10].into_iter().map(Ok::<i32, i32>));
+ 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::<i32, _>(i)), Err(0));
+ assert_eq!(
+ it.clone()
+ .max_by_key(|&i| if i > 0 { Err(i) } else { Ok(-i) }),
+ Err(3)
+ );
+}
+
+#[test]
+fn max_by() {
+ let it = convert(vec![0, 3, 1, -10].into_iter().map(Ok::<i32, ()>));
+ 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::<i32, ()>));
+ assert_eq!(it.min().unwrap(), Some(-10));
+}
+
+#[test]
+fn min_by_key() {
+ let it = convert(vec![0, 3, 1, -10].into_iter().map(Ok::<i32, i32>));
+ 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::<i32, _>(i)), Err(0));
+ assert_eq!(
+ it.clone()
+ .min_by_key(|&i| if i > 0 { Err(i) } else { Ok(-i) }),
+ Err(3)
+ );
+}
+
+#[test]
+fn min_by() {
+ let it = convert(vec![0, 3, 1, -10].into_iter().map(Ok::<i32, ()>));
+ 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::<i32, ()>));
+ assert_eq!(it.nth(1).unwrap(), Some(1));
+ assert_eq!(it.nth(0).unwrap(), Some(2));
+ assert_eq!(it.nth(2).unwrap(), None);
+}
+
+#[test]
+fn peekable() {
+ let mut it = convert(vec![0, 1].into_iter().map(Ok::<i32, ()>)).peekable();
+ assert_eq!(it.peek().unwrap(), Some(&0));
+ assert_eq!(it.peek().unwrap(), Some(&0));
+ assert_eq!(it.next().unwrap(), Some(0));
+ assert_eq!(it.next().unwrap(), Some(1));
+ assert_eq!(it.peek().unwrap(), None);
+ assert_eq!(it.next().unwrap(), None);
+}
+
+#[test]
+fn position() {
+ let mut it = convert(vec![1, 2, 3, 4].into_iter().map(Ok::<i32, ()>));
+ 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::<i32, i32>));
+ 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 scan() {
+ let it = convert(vec![1, 2, 3, 4].into_iter().map(Ok::<i32, ()>)).scan(0, |st, v| {
+ if v > 3 {
+ Ok(None)
+ } else {
+ *st += v;
+ Ok(Some(-*st))
+ }
+ });
+ assert_eq!(it.collect::<Vec<_>>(), Ok(vec![-1, -3, -6]));
+}
+
+#[test]
+fn skip() {
+ let it = convert(vec![1, 2, 3, 4].into_iter().map(Ok::<i32, ()>));
+ assert_eq!(it.clone().skip(0).collect::<Vec<_>>(), Ok(vec![1, 2, 3, 4]));
+ assert_eq!(it.clone().skip(2).collect::<Vec<_>>(), Ok(vec![3, 4]));
+ assert_eq!(it.clone().skip(4).collect::<Vec<_>>(), Ok(vec![]));
+}
+
+#[test]
+fn skip_while() {
+ let it = convert(vec![1, 2, 3, 4, 1].into_iter().map(Ok::<i32, ()>));
+ assert_eq!(
+ it.clone().skip_while(|x| Ok(*x < 1)).collect::<Vec<_>>(),
+ Ok(vec![1, 2, 3, 4, 1])
+ );
+ assert_eq!(
+ it.clone().skip_while(|x| Ok(*x < 3)).collect::<Vec<_>>(),
+ Ok(vec![3, 4, 1])
+ );
+ assert_eq!(
+ it.clone().skip_while(|x| Ok(*x < 5)).collect::<Vec<_>>(),
+ Ok(vec![])
+ );
+}
+
+#[test]
+fn step_by() {
+ let it = convert(
+ vec![0, 1, 2, 3, 4, 5, 6, 7, 8]
+ .into_iter()
+ .map(Ok::<i32, ()>),
+ )
+ .step_by(3);
+ assert_eq!(it.collect::<Vec<_>>(), Ok(vec![0, 3, 6]));
+}
+
+#[test]
+fn take() {
+ let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::<i32, ()>)).take(2);
+ assert_eq!(it.collect::<Vec<_>>().unwrap(), [0, 1]);
+}
+
+#[test]
+fn take_while() {
+ let it = convert(vec![0, 1, 2, 3, 0].into_iter().map(Ok::<i32, ()>));
+ assert_eq!(
+ it.clone().take_while(|x| Ok(*x < 0)).collect::<Vec<_>>(),
+ Ok(vec![])
+ );
+ assert_eq!(
+ it.clone().take_while(|x| Ok(*x < 2)).collect::<Vec<_>>(),
+ Ok(vec![0, 1])
+ );
+ assert_eq!(
+ it.clone().take_while(|x| Ok(*x < 4)).collect::<Vec<_>>(),
+ 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::<Range<i32>, ()>))
+ .flat_map(|r| Ok(convert(r.map(Ok::<i32, ()>))));
+ assert_eq!(it.collect::<Vec<_>>(), Ok(vec![0, 1, 2, 3, 4]));
+}
+
+#[test]
+fn flatten() {
+ let it = convert(
+ vec![0..1, 0..0, 1..5]
+ .into_iter()
+ .map(|r| convert(r.map(Ok::<i32, ()>)))
+ .map(Ok::<_, ()>),
+ )
+ .flatten();
+ assert_eq!(it.collect::<Vec<_>>(), 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::<i32, ()>)).inspect(|v| Ok(buf.push(*v)));
+ 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::<i32, ()>));
+ let (even, odd): (Vec<i32>, Vec<i32>) = it.partition(|i| Ok(*i % 2 == 0)).unwrap();
+ 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::<i32, ()>));
+ assert_eq!(
+ it.find_map(|v| match v {
+ 2 => Ok(Some("hi")),
+ _ => Ok(None),
+ }),
+ 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<i32>, Vec<i32>) = 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::<i32, ()>)).cycle();
+ assert_eq!(it.take(6).clone().collect::<Vec<_>>(), Ok(vec![0, 1, 2, 3, 0, 1]));
+}