fallible-iterator-0.3.0/.cargo_vcs_info.json0000644000000001360000000000100144350ustar { "git": { "sha1": "11cfa0558045e52bdb473c9eab6a1eb35a54e302" }, "path_in_vcs": "" }fallible-iterator-0.3.0/.github/workflows/rust.yml000064400000000000000000000011701046102023000203410ustar 00000000000000on: [push, pull_request] name: Continuous integration jobs: test: name: Test Suite runs-on: ubuntu-latest strategy: matrix: rust: - stable - beta - nightly - 1.36.0 # MSRV steps: - uses: actions/checkout@v3 - name: Install rust nightly uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - uses: taiki-e/install-action@v2 with: tool: cargo-hack - run: cargo hack build --feature-powerset --all-targets - run: cargo hack test --feature-powerset --all-targets fallible-iterator-0.3.0/.gitignore000064400000000000000000000000371046102023000152150ustar 00000000000000target Cargo.lock .idea/ *.iml fallible-iterator-0.3.0/CHANGELOG.md000064400000000000000000000025341046102023000150420ustar 00000000000000# Change Log ## [v0.3.0] - 2023-05-22 ### Removed * `FromFallibleIterator` trait is removed, `FallibleIterator::collect` now requires `std::iter::FromIterator`, which has strictly more implementations. ### Added * add convenient wrapper for std::iter::Iterator * more utilities mirroring std::iter * Peekable methods * `IteratorExt` for convenient conversion * `FallibleIterator::unwrap` ## [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 fallible-iterator-0.3.0/Cargo.toml0000644000000015240000000000100124350ustar # 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 are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "fallible-iterator" version = "0.3.0" authors = ["Steven Fackler "] 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 = ["alloc"] std = ["alloc"] fallible-iterator-0.3.0/Cargo.toml.orig000064400000000000000000000007031046102023000161140ustar 00000000000000[package] name = "fallible-iterator" version = "0.3.0" authors = ["Steven Fackler "] 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] default = ["alloc"] alloc = [] # Legacy feature, no longer needed but retained for backwards compatibility. std = ["alloc"] fallible-iterator-0.3.0/LICENSE-APACHE000064400000000000000000000261361046102023000151610ustar 00000000000000 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. fallible-iterator-0.3.0/LICENSE-MIT000064400000000000000000000020661046102023000146650ustar 00000000000000Copyright (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. fallible-iterator-0.3.0/README.md000064400000000000000000000013361046102023000145070ustar 00000000000000[![crates.io](https://img.shields.io/crates/v/fallible-iterator.svg)](https://crates.io/crates/fallible-iterator) [![docs.rs](https://docs.rs/fallible-iterator/badge.svg)](https://docs.rs/fallible-iterator) ![Continuous integration](https://github.com/sfackler/rust-fallible-iterator/actions/workflows/rust.yml/badge.svg?branch=master&event=push) # rust-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`. fallible-iterator-0.3.0/src/lib.rs000064400000000000000000002163361046102023000151430ustar 00000000000000//! "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` values; for example, the `Lines` iterator //! returns `io::Result`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, //! Self::Error>` rather than `Option`. 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` 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.2")] #![warn(missing_docs)] #![no_std] use core::cmp::{self, Ordering}; use core::convert::Infallible; use core::iter; use core::marker::PhantomData; #[cfg(feature = "alloc")] extern crate alloc; #[cfg(feature = "alloc")] use alloc::boxed::Box; #[cfg(all(test, feature = "alloc"))] 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. 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 implementation defined. fn next(&mut self) -> Result, 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) { (0, None) } /// Consumes the iterator, returning the number of remaining items. #[inline] fn count(self) -> Result where Self: Sized, { self.fold(0, |n, _| Ok(n + 1)) } /// Returns the last element of the iterator. #[inline] fn last(self) -> Result, 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, 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 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(self, it: I) -> Chain where I: IntoFallibleIterator, 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(self, o: I) -> Zip where Self: Sized, I: IntoFallibleIterator, { Zip(self, o.into_fallible_iter()) } /// Returns an iterator which applies a fallible transform to the elements /// of the underlying iterator. #[inline] fn map(self, f: F) -> Map where Self: Sized, F: FnMut(Self::Item) -> Result, { Map { it: self, 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. #[inline] fn filter(self, f: F) -> Filter where Self: Sized, F: FnMut(&Self::Item) -> Result, { Filter { it: self, 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(self, f: F) -> FilterMap where Self: Sized, F: FnMut(Self::Item) -> Result, Self::Error>, { FilterMap { it: self, f } } /// Returns an iterator which yields the current iteration count as well /// as the value. #[inline] fn enumerate(self) -> Enumerate 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 where Self: Sized, { Peekable { it: self, next: None, } } /// 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 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 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] fn take(self, n: usize) -> Take where Self: Sized, { Take { it: self, remaining: n, } } /// 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 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 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)`. /// /// 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 where Self: Sized, { Fuse { it: self, done: false, } } /// 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 /// 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: iter::FromIterator, Self: Sized, { self.iterator().collect() } /// 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. #[inline] 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) } /// Determines if all elements of this iterator match a predicate. #[inline] fn all(&mut self, mut f: F) -> Result where Self: Sized, F: FnMut(Self::Item) -> Result, { 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(&mut self, mut f: F) -> Result where Self: Sized, F: FnMut(Self::Item) -> Result, { 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(&mut self, mut f: F) -> Result, Self::Error> where Self: Sized, F: FnMut(&Self::Item) -> Result, { 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(&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. #[inline] fn position(&mut self, mut f: F) -> Result, Self::Error> where Self: Sized, F: FnMut(Self::Item) -> Result, { 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, 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(mut self, mut f: F) -> Result, Self::Error> where Self: Sized, B: Ord, F: FnMut(&Self::Item) -> Result, { 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(mut self, mut f: F) -> Result, Self::Error> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Result, { 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, 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(mut self, mut f: F) -> Result, Self::Error> where Self: Sized, B: Ord, F: FnMut(&Self::Item) -> Result, { 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(mut self, mut f: F) -> Result, Self::Error> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Result, { 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 where Self: Sized + DoubleEndedFallibleIterator, { 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 where Self: Sized + FallibleIterator, T: 'a + Clone, { Cloned(self) } /// Returns an iterator which repeats 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] fn cmp(mut self, other: I) -> Result where Self: Sized, I: IntoFallibleIterator, 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(mut self, other: I) -> Result, Self::Error> where Self: Sized, I: IntoFallibleIterator, Self::Item: PartialOrd, { 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(mut self, other: I) -> Result where Self: Sized, I: IntoFallibleIterator, Self::Item: PartialEq, { 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(mut self, other: I) -> Result where Self: Sized, I: IntoFallibleIterator, Self::Item: PartialEq, { 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(mut self, other: I) -> Result where Self: Sized, I: IntoFallibleIterator, Self::Item: PartialOrd, { 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(mut self, other: I) -> Result where Self: Sized, I: IntoFallibleIterator, Self::Item: PartialOrd, { 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(mut self, other: I) -> Result where Self: Sized, I: IntoFallibleIterator, Self::Item: PartialOrd, { 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(mut self, other: I) -> Result where Self: Sized, I: IntoFallibleIterator, Self::Item: PartialOrd, { 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`. #[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 } } /// Returns an iterator which unwraps all of its elements. #[inline] fn unwrap(self) -> Unwrap where Self: Sized + FallibleIterator, Self::Error: core::fmt::Debug, { Unwrap(self) } } impl FallibleIterator for &mut I { type Item = I::Item; type Error = I::Error; #[inline] fn next(&mut self) -> Result, I::Error> { (**self).next() } #[inline] 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 { #[inline] fn next_back(&mut self) -> Result, I::Error> { (**self).next_back() } } #[cfg(feature = "alloc")] impl FallibleIterator for Box { type Item = I::Item; type Error = I::Error; #[inline] fn next(&mut self) -> Result, I::Error> { (**self).next() } #[inline] fn size_hint(&self) -> (usize, Option) { (**self).size_hint() } #[inline] fn nth(&mut self, n: usize) -> Result, I::Error> { (**self).nth(n) } } #[cfg(feature = "alloc")] impl DoubleEndedFallibleIterator for Box { #[inline] fn next_back(&mut self) -> Result, 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, Self::Error>; /// Applies a function over the elements of the iterator in reverse order, producing a single final value. #[inline] 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)?; } Ok(init) } } /// 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; /// Creates a fallible iterator from a value. fn into_fallible_iter(self) -> Self::IntoFallibleIter; } impl 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)] pub struct Map { it: T, f: F, } impl core::fmt::Debug for Map { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("Map").field("iter", &self.it).finish() } } impl FallibleIterator for Map where T: FallibleIterator, F: FnMut(T::Item) -> Result, { type Item = B; type Error = T::Error; #[inline] fn next(&mut self) -> Result, 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) { self.it.size_hint() } #[inline] fn try_fold(&mut self, init: C, mut f: G) -> Result where E: From, G: FnMut(C, B) -> Result, { let map = &mut self.f; self.it.try_fold(init, |b, v| f(b, map(v)?)) } } 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((self.f)(v)?)), Ok(None) => Ok(None), Err(e) => Err(e), } } #[inline] fn try_rfold(&mut self, init: C, mut f: G) -> Result where E: From, G: FnMut(C, B) -> Result, { 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 { front: T, back: U, state: ChainState, } impl FallibleIterator for Chain where T: FallibleIterator, U: FallibleIterator, { type Item = T::Item; type Error = T::Error; #[inline] fn next(&mut self) -> Result, 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) { 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 { 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(&mut self, init: B, mut f: F) -> Result where E: From, F: FnMut(B, T::Item) -> Result, { 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(&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 where T: DoubleEndedFallibleIterator, U: DoubleEndedFallibleIterator, { #[inline] fn next_back(&mut self) -> Result, 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(&mut self, init: B, mut f: F) -> Result where E: From, F: FnMut(B, T::Item) -> Result, { 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); impl<'a, T, I> FallibleIterator for Cloned where I: FallibleIterator, T: 'a + Clone, { type Item = T; type Error = I::Error; #[inline] fn next(&mut self) -> Result, I::Error> { self.0.next().map(|o| o.cloned()) } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } #[inline] fn try_fold(&mut self, init: B, mut f: F) -> Result where E: From, F: FnMut(B, T) -> Result, { self.0.try_fold(init, |acc, v| f(acc, v.clone())) } } impl<'a, T, I> DoubleEndedFallibleIterator for Cloned where I: DoubleEndedFallibleIterator, T: 'a + Clone, { #[inline] fn next_back(&mut self) -> Result, I::Error> { self.0.next_back().map(|o| o.cloned()) } #[inline] fn try_rfold(&mut self, init: B, mut f: F) -> Result where E: From, F: FnMut(B, T) -> Result, { self.0.try_rfold(init, |acc, v| f(acc, v.clone())) } } /// Converts an `Iterator>` into a `FallibleIterator`. #[inline] pub fn convert(it: I) -> Convert where I: iter::Iterator>, { Convert(it) } /// A fallible iterator that wraps a normal iterator over `Result`s. #[derive(Clone, Debug)] pub struct Convert(I); impl FallibleIterator for Convert where I: iter::Iterator>, { type Item = T; type Error = E; #[inline] fn next(&mut self) -> Result, 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) { self.0.size_hint() } #[inline] fn try_fold(&mut self, init: B, mut f: F) -> Result where E2: From, F: FnMut(B, T) -> Result, { self.0.try_fold(init, |acc, v| f(acc, v?)) } } impl DoubleEndedFallibleIterator for Convert where I: DoubleEndedIterator>, { #[inline] fn next_back(&mut self) -> Result, E> { match self.0.next_back() { Some(Ok(i)) => Ok(Some(i)), Some(Err(e)) => Err(e), None => Ok(None), } } #[inline] fn try_rfold(&mut self, init: B, mut f: F) -> Result where E2: From, F: FnMut(B, T) -> Result, { self.0.try_rfold(init, |acc, v| f(acc, v?)) } } /// A fallible iterator that wraps a normal iterator over `Result`s. #[derive(Clone, Debug)] pub struct IntoFallible(I); impl FallibleIterator for IntoFallible where I: iter::Iterator, { type Item = T; type Error = Infallible; #[inline] fn next(&mut self) -> Result, Self::Error> { Ok(self.0.next()) } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } #[inline] fn try_fold(&mut self, init: B, f: F) -> Result where E2: From, F: FnMut(B, T) -> Result, { self.0.try_fold(init, f) } } impl> From for IntoFallible { fn from(value: I) -> Self { Self(value) } } impl DoubleEndedFallibleIterator for IntoFallible where I: DoubleEndedIterator, { #[inline] fn next_back(&mut self) -> Result, Infallible> { Ok(self.0.next_back()) } #[inline] fn try_rfold(&mut self, init: B, f: F) -> Result where E2: From, F: FnMut(B, T) -> Result, { self.0.try_rfold(init, f) } } /// An iterator that yields the iteration count as well as the values of the /// underlying iterator. #[derive(Clone, Debug)] pub struct Enumerate { it: I, n: usize, } impl FallibleIterator for Enumerate 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) }) }) } #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } #[inline] 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 try_fold(&mut self, init: B, mut f: F) -> Result where E: From, F: FnMut(B, (usize, I::Item)) -> Result, { 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 { it: I, f: F, } impl FallibleIterator for Filter where I: FallibleIterator, F: FnMut(&I::Item) -> Result, { type Item = I::Item; type Error = I::Error; #[inline] fn next(&mut self) -> Result, 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) { (0, self.it.size_hint().1) } #[inline] fn try_fold(&mut self, init: B, mut f: G) -> Result where E: From, G: FnMut(B, I::Item) -> Result, { let predicate = &mut self.f; self.it.try_fold( init, |acc, v| { if predicate(&v)? { f(acc, v) } else { Ok(acc) } }, ) } } impl DoubleEndedFallibleIterator for Filter where I: DoubleEndedFallibleIterator, F: FnMut(&I::Item) -> Result, { #[inline] fn next_back(&mut self) -> Result, 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(&mut self, init: B, mut f: G) -> Result where E: From, G: FnMut(B, I::Item) -> Result, { 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 { it: I, f: F, } impl FallibleIterator for FilterMap where I: FallibleIterator, F: FnMut(I::Item) -> Result, I::Error>, { type Item = B; type Error = I::Error; #[inline] fn next(&mut self) -> Result, 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) { (0, self.it.size_hint().1) } #[inline] fn try_fold(&mut self, init: C, mut f: G) -> Result where E: From, G: FnMut(C, B) -> Result, { let map = &mut self.f; self.it.try_fold(init, |acc, v| match map(v)? { Some(v) => f(acc, v), None => Ok(acc), }) } } impl DoubleEndedFallibleIterator for FilterMap where I: DoubleEndedFallibleIterator, F: FnMut(I::Item) -> Result, I::Error>, { #[inline] fn next_back(&mut self) -> Result, 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(&mut self, init: C, mut f: G) -> Result where E: From, G: FnMut(C, B) -> Result, { 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 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_iter()), None => return Ok(None), } } } #[inline] fn try_fold(&mut self, init: B, mut f: G) -> Result where E: From, G: FnMut(B, U::Item) -> Result, { 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 where I: FallibleIterator, I::Item: IntoFallibleIterator, { it: I, cur: Option<::IntoFallibleIter>, } impl Clone for Flatten where I: FallibleIterator + Clone, I::Item: IntoFallibleIterator, ::IntoFallibleIter: 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_iter()), None => return Ok(None), } } } #[inline] fn try_fold(&mut self, init: B, mut f: G) -> Result where E: From, G: FnMut(B, Self::Item) -> Result, { 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) } } }) } } /// Creates an iterator from a fallible function generating values. /// /// ``` /// # use fallible_iterator::{from_fn, FallibleIterator}; /// let mut count = 0; /// let counter = from_fn(move || { /// // Increment our count. This is why we started at zero. /// count += 1; /// /// // Check to see if we've finished counting or not. /// if count < 6 { /// Ok(Some(count)) /// } else if count < 7 { /// Ok(None) /// } else { /// Err(()) /// } /// }); /// assert_eq!(&counter.collect::>().unwrap(), &[1, 2, 3, 4, 5]); /// ``` #[inline] pub fn from_fn(fun: F) -> FromFn where F: FnMut() -> Result, E>, { FromFn { fun } } /// An iterator using a function to generate new values. #[derive(Clone, Debug)] pub struct FromFn { fun: F, } impl FallibleIterator for FromFn where F: FnMut() -> Result, E>, { type Item = I; type Error = E; fn next(&mut self) -> Result, E> { (self.fun)() } } /// An iterator that yields `Ok(None)` forever after the underlying iterator /// yields `Ok(None)` once. #[derive(Clone, Debug)] pub struct Fuse { it: I, done: bool, } impl FallibleIterator for Fuse where I: FallibleIterator, { type Item = I::Item; type Error = I::Error; #[inline] fn next(&mut self) -> Result, 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) { if self.done { (0, Some(0)) } else { self.it.size_hint() } } #[inline] fn count(self) -> Result { if self.done { Ok(0) } else { 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 try_fold(&mut self, init: B, f: F) -> Result where E: From, F: FnMut(B, I::Item) -> Result, { 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 { 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() } #[inline] fn try_fold(&mut self, init: B, mut f: G) -> Result where E: From, G: FnMut(B, I::Item) -> Result, { let inspect = &mut self.f; self.it.try_fold(init, |acc, v| { inspect(&v)?; f(acc, v) }) } } 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), } } #[inline] fn try_rfold(&mut self, init: B, mut f: G) -> Result where E: From, G: FnMut(B, I::Item) -> Result, { 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); impl iter::Iterator for Iterator where I: FallibleIterator, { type Item = Result; #[inline] fn next(&mut self) -> Option> { 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) { self.0.size_hint() } } impl DoubleEndedIterator for Iterator where I: DoubleEndedFallibleIterator, { #[inline] fn next_back(&mut self) -> Option> { 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 { it: I, f: F, } impl FallibleIterator for MapErr where I: FallibleIterator, F: FnMut(I::Error) -> B, { type Item = I::Item; type Error = B; #[inline] fn next(&mut self) -> Result, B> { self.it.next().map_err(&mut self.f) } #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } #[inline] 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) } #[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 where I: DoubleEndedFallibleIterator, F: FnMut(I::Error) -> B, { #[inline] 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. #[derive(Clone, Debug)] pub struct Peekable { it: I, next: Option, } impl Peekable where I: FallibleIterator, { /// Returns a reference to the next value without advancing the iterator. #[inline] pub fn peek(&mut self) -> Result, I::Error> { if self.next.is_none() { self.next = self.it.next()?; } Ok(self.next.as_ref()) } /// Consume and return the next value of this iterator if a condition is true. /// /// If func returns true for the next value of this iterator, consume and return it. Otherwise, return None. #[inline] pub fn next_if(&mut self, f: impl Fn(&I::Item) -> bool) -> Result, I::Error> { match self.peek()? { Some(item) if f(item) => self.next(), _ => Ok(None), } } /// Consume and return the next item if it is equal to `expected`. #[inline] pub fn next_if_eq(&mut self, expected: &T) -> Result, I::Error> where T: ?Sized, I::Item: PartialEq, { self.next_if(|found| found == expected) } } impl FallibleIterator for Peekable where I: FallibleIterator, { type Item = I::Item; type Error = I::Error; #[inline] fn next(&mut self) -> Result, I::Error> { if let Some(next) = self.next.take() { return Ok(Some(next)); } self.it.next() } #[inline] fn size_hint(&self) -> (usize, Option) { 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(&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 /// order. #[derive(Clone, Debug)] pub struct Rev(I); impl FallibleIterator for Rev where I: DoubleEndedFallibleIterator, { type Item = I::Item; type Error = I::Error; #[inline] fn next(&mut self) -> Result, I::Error> { self.0.next_back() } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } #[inline] fn count(self) -> Result { self.0.count() } #[inline] fn try_fold(&mut self, init: B, f: F) -> Result where E: From, F: FnMut(B, I::Item) -> Result, { self.0.try_rfold(init, f) } } impl DoubleEndedFallibleIterator for Rev where I: DoubleEndedFallibleIterator, { #[inline] fn next_back(&mut self) -> Result, I::Error> { self.0.next() } #[inline] fn try_rfold(&mut self, init: B, f: F) -> Result where E: From, F: FnMut(B, I::Item) -> Result, { self.0.try_fold(init, f) } } /// 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 { 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 { 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 { 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)] pub struct Take { it: I, remaining: usize, } impl FallibleIterator for Take where I: FallibleIterator, { type Item = I::Item; type Error = I::Error; #[inline] fn next(&mut self) -> Result, 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) { 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 { 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 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)] pub struct Zip(T, U); impl FallibleIterator for Zip where T: FallibleIterator, U: FallibleIterator, { type Item = (T::Item, U::Item); type Error = T::Error; #[inline] fn next(&mut self) -> Result, 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) { 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) } } /// An iterator that unwraps every element yielded by the underlying /// FallibleIterator #[derive(Clone, Debug)] pub struct Unwrap(T); impl iter::Iterator for Unwrap where T: FallibleIterator, T::Error: core::fmt::Debug, { type Item = T::Item; #[inline] fn next(&mut self) -> Option { self.0.next().unwrap() } #[inline] fn size_hint(&self) -> (usize, Option) { let (_, max) = self.0.size_hint(); (0, max) } } fn _is_object_safe(_: &dyn DoubleEndedFallibleIterator) {} /// An extnsion-trait with set of useful methods to convert [`core::iter::Iterator`] /// into [`FallibleIterator`] pub trait IteratorExt { /// Convert an iterator of `Result`s into `FallibleIterator` by transposition fn transpose_into_fallible(self) -> Convert where Self: iter::Iterator> + Sized; /// Convert an iterator of anything into `FallibleIterator` by wrapping /// into `Result` where `Infallible` is an error that can never actually /// happen. fn into_fallible(self) -> IntoFallible where Self: iter::Iterator + Sized; } impl IteratorExt for I where I: iter::Iterator, { /// Convert an iterator of `Result`s into `FallibleIterator` by transposition fn transpose_into_fallible(self) -> Convert where Self: iter::Iterator> + Sized, { Convert(self) } /// Convert an iterator of anything into `FallibleIterator` by wrapping /// into `Result` where `Infallible` is an error that can never actually /// happen. fn into_fallible(self) -> IntoFallible where Self: iter::Iterator + Sized, { IntoFallible(self) } } /// An iterator that yields nothing. #[derive(Clone, Debug)] pub struct Empty(PhantomData, PhantomData); impl FallibleIterator for Empty { type Item = T; type Error = E; #[inline] fn next(&mut self) -> Result, E> { Ok(None) } #[inline] fn size_hint(&self) -> (usize, Option) { (0, Some(0)) } } /// Creates an iterator that yields nothing. pub fn empty() -> Empty { Empty(PhantomData, PhantomData) } /// An iterator that yields something exactly once. #[derive(Clone, Debug)] pub struct Once(Option, PhantomData); /// Creates an iterator that yields an element exactly once. pub fn once(value: T) -> Once { Once(Some(value), PhantomData) } impl FallibleIterator for Once { type Item = T; type Error = E; #[inline] fn next(&mut self) -> Result, Self::Error> { Ok(self.0.take()) } #[inline] fn size_hint(&self) -> (usize, Option) { match self.0 { Some(_) => (1, Some(1)), None => (0, Some(0)), } } } /// An iterator that fails with a predetermined error exactly once. #[derive(Clone, Debug)] pub struct OnceErr(PhantomData, Option); /// Creates an iterator that fails with a predetermined error exactly once. pub fn once_err(value: E) -> OnceErr { OnceErr(PhantomData, Some(value)) } impl FallibleIterator for OnceErr { type Item = T; type Error = E; #[inline] fn next(&mut self) -> Result, Self::Error> { match self.1.take() { Some(value) => Err(value), None => Ok(None), } } #[inline] fn size_hint(&self) -> (usize, Option) { (0, Some(0)) } } /// An iterator that endlessly repeats a single element. #[derive(Clone, Debug)] pub struct Repeat(T, PhantomData); /// Creates an iterator that endlessly repeats a single element. pub fn repeat(value: T) -> Repeat { Repeat(value, PhantomData) } impl FallibleIterator for Repeat { type Item = T; type Error = E; #[inline] fn next(&mut self) -> Result, Self::Error> { Ok(Some(self.0.clone())) } #[inline] fn size_hint(&self) -> (usize, Option) { (usize::max_value(), None) } } /// An iterator that endlessly repeats a single error. #[derive(Clone, Debug)] pub struct RepeatErr(PhantomData, E); /// Creates an iterator that endlessly repeats a single error. pub fn repeat_err(value: E) -> RepeatErr { RepeatErr(PhantomData, value) } impl FallibleIterator for RepeatErr { type Item = T; type Error = E; #[inline] fn next(&mut self) -> Result, Self::Error> { Err(self.1.clone()) } #[inline] fn size_hint(&self) -> (usize, Option) { (0, Some(0)) } } fallible-iterator-0.3.0/src/test.rs000064400000000000000000000311321046102023000153410ustar 00000000000000use alloc::{vec, vec::Vec}; use core::{iter, ops::Range}; use super::{convert, FallibleIterator, IntoFallible}; #[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::)); let b = convert(vec![4, 5, 6, 7].into_iter().map(Ok::)); let it = a.chain(b); assert_eq!(it.collect::>().unwrap(), [0, 1, 2, 3, 4, 5, 6, 7]); let a = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)); let b = convert(vec![4, 5, 6, 7].into_iter().map(Ok::)); let it = a.chain(b).rev(); assert_eq!(it.collect::>().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::)).enumerate(); 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) }); 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() { 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)); 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::)); 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::)); 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 { 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] 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) }), ); 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, 4].into_iter().map(Ok::)).map(|n| Ok(n * 2)); fn assert_debug(_: &impl core::fmt::Debug) {} assert_debug(&it); 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 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::>(), Err(1)); assert_eq!(it.rev().collect::>(), Err(3)); } #[test] fn max() { let it = convert(vec![0, 3, 1, -10].into_iter().map(Ok::)); assert_eq!(it.max().unwrap(), Some(3)); } #[test] fn max_by_key() { 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.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::)); 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::)); assert_eq!(it.min().unwrap(), Some(-10)); } #[test] fn min_by_key() { 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.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::)); 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::)); 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::)).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::)); 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 mut 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.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::)).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::)); 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.skip(4).collect::>(), Ok(vec![])); } #[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.skip_while(|x| Ok(*x < 5)).collect::>(), Ok(vec![]) ); } #[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); 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.take_while(|x| Ok(*x < 4)).collect::>(), 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])); } #[test] fn flatten() { let it = convert( vec![0..1, 0..0, 1..5] .into_iter() .map(|r| convert(r.map(Ok::))) .map(Ok::<_, ()>), ) .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| { buf.push(v); Ok(()) }); 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]); } #[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")) ); } #[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]); } #[test] fn cycle() { let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)).cycle(); assert_eq!(it.take(6).collect::>(), Ok(vec![0, 1, 2, 3, 0, 1])); } #[test] fn unwrap() { let it = convert(vec![0, 1, 2, 3].into_iter().map(Ok::)).unwrap(); assert_eq!(it.collect::>(), vec![0, 1, 2, 3]); } #[test] #[should_panic] fn unwrap_panic() { let _ = convert(vec![Ok(0), Err(())].into_iter()) .unwrap() .collect::>(); } #[test] fn wrap_std_iter_into_fallible() { let it = IntoFallible::from(vec![0, 1, 2, 3].into_iter()); assert_eq!(it.collect::>().unwrap(), vec![0, 1, 2, 3]); }