diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/fallible-iterator/src | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/fallible-iterator/src')
-rw-r--r-- | third_party/rust/fallible-iterator/src/lib.rs | 2606 | ||||
-rw-r--r-- | third_party/rust/fallible-iterator/src/test.rs | 455 |
2 files changed, 3061 insertions, 0 deletions
diff --git a/third_party/rust/fallible-iterator/src/lib.rs b/third_party/rust/fallible-iterator/src/lib.rs new file mode 100644 index 0000000000..f5f77b257d --- /dev/null +++ b/third_party/rust/fallible-iterator/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/third_party/rust/fallible-iterator/src/test.rs b/third_party/rust/fallible-iterator/src/test.rs new file mode 100644 index 0000000000..f7627c4a34 --- /dev/null +++ b/third_party/rust/fallible-iterator/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])); +} |