Skip to content

Commit

Permalink
Move the iter methods back to the root for doc order
Browse files Browse the repository at this point in the history
  • Loading branch information
cuviper committed Feb 10, 2024
1 parent 2a37eba commit 499b9ed
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 170 deletions.
173 changes: 6 additions & 167 deletions src/iterator.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
use super::{for_both, Either, Left, Right};
use core::iter;

macro_rules! map_either {
($value:expr, $pattern:pat => $result:expr) => {
match $value {
Left($pattern) => Left($result),
Right($pattern) => Right($result),
}
};
}

macro_rules! wrap_either {
($value:expr => $( $tail:tt )*) => {
match $value {
Expand All @@ -19,164 +10,6 @@ macro_rules! wrap_either {
};
}

impl<L, R> Either<L, R> {
/// Convert the inner value to an iterator.
///
/// This requires the `Left` and `Right` iterators to have the same item type.
/// See [`factor_into_iter`][Either::factor_into_iter] to iterate different types.
///
/// ```
/// use either::*;
///
/// let left: Either<_, Vec<u32>> = Left(vec![1, 2, 3, 4, 5]);
/// let mut right: Either<Vec<u32>, _> = Right(vec![]);
/// right.extend(left.into_iter());
/// assert_eq!(right, Right(vec![1, 2, 3, 4, 5]));
/// ```
#[allow(clippy::should_implement_trait)]
pub fn into_iter(self) -> Either<L::IntoIter, R::IntoIter>
where
L: IntoIterator,
R: IntoIterator<Item = L::Item>,
{
map_either!(self, inner => inner.into_iter())
}

/// Borrow the inner value as an iterator.
///
/// This requires the `Left` and `Right` iterators to have the same item type.
/// See [`factor_iter`][Either::factor_iter] to iterate different types.
///
/// ```
/// use either::*;
///
/// let left: Either<_, &[u32]> = Left(vec![2, 3]);
/// let mut right: Either<Vec<u32>, _> = Right(&[4, 5][..]);
/// let mut all = vec![1];
/// all.extend(left.iter());
/// all.extend(right.iter());
/// assert_eq!(all, vec![1, 2, 3, 4, 5]);
/// ```
pub fn iter(&self) -> Either<<&L as IntoIterator>::IntoIter, <&R as IntoIterator>::IntoIter>
where
for<'a> &'a L: IntoIterator,
for<'a> &'a R: IntoIterator<Item = <&'a L as IntoIterator>::Item>,
{
map_either!(self, inner => inner.into_iter())
}

/// Mutably borrow the inner value as an iterator.
///
/// This requires the `Left` and `Right` iterators to have the same item type.
/// See [`factor_iter_mut`][Either::factor_iter_mut] to iterate different types.
///
/// ```
/// use either::*;
///
/// let mut left: Either<_, &mut [u32]> = Left(vec![2, 3]);
/// for l in left.iter_mut() {
/// *l *= *l
/// }
/// assert_eq!(left, Left(vec![4, 9]));
///
/// let mut inner = [4, 5];
/// let mut right: Either<Vec<u32>, _> = Right(&mut inner[..]);
/// for r in right.iter_mut() {
/// *r *= *r
/// }
/// assert_eq!(inner, [16, 25]);
/// ```
pub fn iter_mut(
&mut self,
) -> Either<<&mut L as IntoIterator>::IntoIter, <&mut R as IntoIterator>::IntoIter>
where
for<'a> &'a mut L: IntoIterator,
for<'a> &'a mut R: IntoIterator<Item = <&'a mut L as IntoIterator>::Item>,
{
map_either!(self, inner => inner.into_iter())
}

/// Converts an `Either` of `Iterator`s to be an `Iterator` of `Either`s
///
/// Unlike [`into_iter`][Either::into_iter], this does not require the
/// `Left` and `Right` iterators to have the same item type.
///
/// ```
/// use either::*;
/// let left: Either<_, Vec<u8>> = Left(&["hello"]);
/// assert_eq!(left.factor_into_iter().next(), Some(Left(&"hello")));

/// let right: Either<&[&str], _> = Right(vec![0, 1]);
/// assert_eq!(right.factor_into_iter().collect::<Vec<_>>(), vec![Right(0), Right(1)]);
///
/// ```
// TODO(MSRV): doc(alias) was stabilized in Rust 1.48
// #[doc(alias = "transpose")]
pub fn factor_into_iter(self) -> IterEither<L::IntoIter, R::IntoIter>
where
L: IntoIterator,
R: IntoIterator,
{
IterEither {
inner: map_either!(self, inner => inner.into_iter()),
}
}

/// Borrows an `Either` of `Iterator`s to be an `Iterator` of `Either`s
///
/// Unlike [`iter`][Either::iter], this does not require the
/// `Left` and `Right` iterators to have the same item type.
///
/// ```
/// use either::*;
/// let left: Either<_, Vec<u8>> = Left(["hello"]);
/// assert_eq!(left.factor_iter().next(), Some(Left(&"hello")));

/// let right: Either<[&str; 2], _> = Right(vec![0, 1]);
/// assert_eq!(right.factor_iter().collect::<Vec<_>>(), vec![Right(&0), Right(&1)]);
///
/// ```
pub fn factor_iter(
&self,
) -> IterEither<<&L as IntoIterator>::IntoIter, <&R as IntoIterator>::IntoIter>
where
for<'a> &'a L: IntoIterator,
for<'a> &'a R: IntoIterator,
{
IterEither {
inner: map_either!(self, inner => inner.into_iter()),
}
}

/// Mutably borrows an `Either` of `Iterator`s to be an `Iterator` of `Either`s
///
/// Unlike [`iter_mut`][Either::iter_mut], this does not require the
/// `Left` and `Right` iterators to have the same item type.
///
/// ```
/// use either::*;
/// let mut left: Either<_, Vec<u8>> = Left(["hello"]);
/// left.factor_iter_mut().for_each(|x| *x.unwrap_left() = "goodbye");
/// assert_eq!(left, Left(["goodbye"]));

/// let mut right: Either<[&str; 2], _> = Right(vec![0, 1, 2]);
/// right.factor_iter_mut().for_each(|x| if let Right(r) = x { *r = -*r; });
/// assert_eq!(right, Right(vec![0, -1, -2]));
///
/// ```
pub fn factor_iter_mut(
&mut self,
) -> IterEither<<&mut L as IntoIterator>::IntoIter, <&mut R as IntoIterator>::IntoIter>
where
for<'a> &'a mut L: IntoIterator,
for<'a> &'a mut R: IntoIterator,
{
IterEither {
inner: map_either!(self, inner => inner.into_iter()),
}
}
}

/// Iterator that maps left or right iterators to corresponding `Either`-wrapped items.
///
/// This struct is created by the [`Either::factor_into_iter`],
Expand All @@ -187,6 +20,12 @@ pub struct IterEither<L, R> {
inner: Either<L, R>,
}

impl<L, R> IterEither<L, R> {
pub(crate) fn new(inner: Either<L, R>) -> Self {
IterEither { inner }
}
}

impl<L, R, A> Extend<A> for Either<L, R>
where
L: Extend<A>,
Expand Down
165 changes: 162 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,18 @@ macro_rules! try_right {
};
}

macro_rules! map_either {
($value:expr, $pattern:pat => $result:expr) => {
match $value {
Left($pattern) => Left($result),
Right($pattern) => Right($result),
}
};
}

mod iterator;
pub use self::iterator::IterEither;

impl<L: Clone, R: Clone> Clone for Either<L, R> {
fn clone(&self) -> Self {
match self {
Expand Down Expand Up @@ -505,6 +517,156 @@ impl<L, R> Either<L, R> {
}
}

/// Convert the inner value to an iterator.
///
/// This requires the `Left` and `Right` iterators to have the same item type.
/// See [`factor_into_iter`][Either::factor_into_iter] to iterate different types.
///
/// ```
/// use either::*;
///
/// let left: Either<_, Vec<u32>> = Left(vec![1, 2, 3, 4, 5]);
/// let mut right: Either<Vec<u32>, _> = Right(vec![]);
/// right.extend(left.into_iter());
/// assert_eq!(right, Right(vec![1, 2, 3, 4, 5]));
/// ```
#[allow(clippy::should_implement_trait)]
pub fn into_iter(self) -> Either<L::IntoIter, R::IntoIter>
where
L: IntoIterator,
R: IntoIterator<Item = L::Item>,
{
map_either!(self, inner => inner.into_iter())
}

/// Borrow the inner value as an iterator.
///
/// This requires the `Left` and `Right` iterators to have the same item type.
/// See [`factor_iter`][Either::factor_iter] to iterate different types.
///
/// ```
/// use either::*;
///
/// let left: Either<_, &[u32]> = Left(vec![2, 3]);
/// let mut right: Either<Vec<u32>, _> = Right(&[4, 5][..]);
/// let mut all = vec![1];
/// all.extend(left.iter());
/// all.extend(right.iter());
/// assert_eq!(all, vec![1, 2, 3, 4, 5]);
/// ```
pub fn iter(&self) -> Either<<&L as IntoIterator>::IntoIter, <&R as IntoIterator>::IntoIter>
where
for<'a> &'a L: IntoIterator,
for<'a> &'a R: IntoIterator<Item = <&'a L as IntoIterator>::Item>,
{
map_either!(self, inner => inner.into_iter())
}

/// Mutably borrow the inner value as an iterator.
///
/// This requires the `Left` and `Right` iterators to have the same item type.
/// See [`factor_iter_mut`][Either::factor_iter_mut] to iterate different types.
///
/// ```
/// use either::*;
///
/// let mut left: Either<_, &mut [u32]> = Left(vec![2, 3]);
/// for l in left.iter_mut() {
/// *l *= *l
/// }
/// assert_eq!(left, Left(vec![4, 9]));
///
/// let mut inner = [4, 5];
/// let mut right: Either<Vec<u32>, _> = Right(&mut inner[..]);
/// for r in right.iter_mut() {
/// *r *= *r
/// }
/// assert_eq!(inner, [16, 25]);
/// ```
pub fn iter_mut(
&mut self,
) -> Either<<&mut L as IntoIterator>::IntoIter, <&mut R as IntoIterator>::IntoIter>
where
for<'a> &'a mut L: IntoIterator,
for<'a> &'a mut R: IntoIterator<Item = <&'a mut L as IntoIterator>::Item>,
{
map_either!(self, inner => inner.into_iter())
}

/// Converts an `Either` of `Iterator`s to be an `Iterator` of `Either`s
///
/// Unlike [`into_iter`][Either::into_iter], this does not require the
/// `Left` and `Right` iterators to have the same item type.
///
/// ```
/// use either::*;
/// let left: Either<_, Vec<u8>> = Left(&["hello"]);
/// assert_eq!(left.factor_into_iter().next(), Some(Left(&"hello")));

/// let right: Either<&[&str], _> = Right(vec![0, 1]);
/// assert_eq!(right.factor_into_iter().collect::<Vec<_>>(), vec![Right(0), Right(1)]);
///
/// ```
// TODO(MSRV): doc(alias) was stabilized in Rust 1.48
// #[doc(alias = "transpose")]
pub fn factor_into_iter(self) -> IterEither<L::IntoIter, R::IntoIter>
where
L: IntoIterator,
R: IntoIterator,
{
IterEither::new(map_either!(self, inner => inner.into_iter()))
}

/// Borrows an `Either` of `Iterator`s to be an `Iterator` of `Either`s
///
/// Unlike [`iter`][Either::iter], this does not require the
/// `Left` and `Right` iterators to have the same item type.
///
/// ```
/// use either::*;
/// let left: Either<_, Vec<u8>> = Left(["hello"]);
/// assert_eq!(left.factor_iter().next(), Some(Left(&"hello")));

/// let right: Either<[&str; 2], _> = Right(vec![0, 1]);
/// assert_eq!(right.factor_iter().collect::<Vec<_>>(), vec![Right(&0), Right(&1)]);
///
/// ```
pub fn factor_iter(
&self,
) -> IterEither<<&L as IntoIterator>::IntoIter, <&R as IntoIterator>::IntoIter>
where
for<'a> &'a L: IntoIterator,
for<'a> &'a R: IntoIterator,
{
IterEither::new(map_either!(self, inner => inner.into_iter()))
}

/// Mutably borrows an `Either` of `Iterator`s to be an `Iterator` of `Either`s
///
/// Unlike [`iter_mut`][Either::iter_mut], this does not require the
/// `Left` and `Right` iterators to have the same item type.
///
/// ```
/// use either::*;
/// let mut left: Either<_, Vec<u8>> = Left(["hello"]);
/// left.factor_iter_mut().for_each(|x| *x.unwrap_left() = "goodbye");
/// assert_eq!(left, Left(["goodbye"]));

/// let mut right: Either<[&str; 2], _> = Right(vec![0, 1, 2]);
/// right.factor_iter_mut().for_each(|x| if let Right(r) = x { *r = -*r; });
/// assert_eq!(right, Right(vec![0, -1, -2]));
///
/// ```
pub fn factor_iter_mut(
&mut self,
) -> IterEither<<&mut L as IntoIterator>::IntoIter, <&mut R as IntoIterator>::IntoIter>
where
for<'a> &'a mut L: IntoIterator,
for<'a> &'a mut R: IntoIterator,
{
IterEither::new(map_either!(self, inner => inner.into_iter()))
}

/// Return left value or given value
///
/// Arguments passed to `left_or` are eagerly evaluated; if you are passing
Expand Down Expand Up @@ -928,9 +1090,6 @@ impl<T> Either<T, T> {
}
}

mod iterator;
pub use iterator::IterEither;

/// Convert from `Result` to `Either` with `Ok => Right` and `Err => Left`.
impl<L, R> From<Result<R, L>> for Either<L, R> {
fn from(r: Result<R, L>) -> Self {
Expand Down

0 comments on commit 499b9ed

Please sign in to comment.