diff --git a/src/iterator.rs b/src/iterator.rs index d54fab7..7e74686 100644 --- a/src/iterator.rs +++ b/src/iterator.rs @@ -185,7 +185,7 @@ where type Item = Either; fn next(&mut self) -> Option { - Some(map_either!(self.inner, ref mut inner => inner.next()?)) + Some(map_both!(self.inner, ref mut inner => inner.next()?)) } fn size_hint(&self) -> (usize, Option) { @@ -211,11 +211,11 @@ where } fn last(self) -> Option { - Some(map_either!(self.inner, inner => inner.last()?)) + Some(map_both!(self.inner, inner => inner.last()?)) } fn nth(&mut self, n: usize) -> Option { - Some(map_either!(self.inner, ref mut inner => inner.nth(n)?)) + Some(map_both!(self.inner, ref mut inner => inner.nth(n)?)) } fn collect(self) -> B @@ -275,11 +275,11 @@ where R: DoubleEndedIterator, { fn next_back(&mut self) -> Option { - Some(map_either!(self.inner, ref mut inner => inner.next_back()?)) + Some(map_both!(self.inner, ref mut inner => inner.next_back()?)) } fn nth_back(&mut self, n: usize) -> Option { - Some(map_either!(self.inner, ref mut inner => inner.nth_back(n)?)) + Some(map_both!(self.inner, ref mut inner => inner.nth_back(n)?)) } fn rfold(self, init: Acc, f: G) -> Acc diff --git a/src/lib.rs b/src/lib.rs index 702f54c..73bd5bd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,6 +60,8 @@ pub enum Either { /// /// Syntax: `either::for_both!(` *expression* `,` *pattern* `=>` *expression* `)` /// +/// Unlike [`map_both!`], this macro converges both variants to the type returned by the expression. +/// /// # Example /// /// ``` @@ -87,6 +89,53 @@ macro_rules! for_both { }; } +/// Evaluate the provided expression for both [`Either::Left`] and [`Either::Right`], +/// returning an [`Either`] with the results. +/// +/// This macro is useful in cases where both sides of [`Either`] can be interacted with +/// in the same way even though the don't share the same type. +/// +/// Syntax: `either::map_both!(` *expression* `,` *pattern* `=>` *expression* `)` +/// +/// Unlike [`for_both!`], this macro returns an [`Either`] with the results of the expressions. +/// +/// # Example +/// +/// ``` +/// use either::Either; +/// +/// struct Wrapper(T); +/// +/// fn wrap( +/// owned_or_borrowed: Either, +/// ) -> Either, Wrapper<&'static str>> { +/// either::map_both!(owned_or_borrowed, s => Wrapper(s)) +/// } +/// ``` +/// +/// ``` +/// use either::Either; +/// +/// fn widen(x: Either) -> Either { +/// either::map_both!(x => x.into()) +/// } +/// ``` +#[macro_export] +macro_rules! map_both { + ($value:expr, $pattern:pat => $result:expr) => { + match $value { + $crate::Either::Left($pattern) => $crate::Either::Left($result), + $crate::Either::Right($pattern) => $crate::Either::Right($result), + } + }; + ($name:ident => $result:expr) => { + match $name { + $crate::Either::Left($name) => $crate::Either::Left($result), + $crate::Either::Right($name) => $crate::Either::Right($result), + } + }; +} + /// Macro for unwrapping the left side of an [`Either`], which fails early /// with the opposite side. Can only be used in functions that return /// `Either` because of the early return of `Right` that it provides. @@ -130,15 +179,6 @@ 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; @@ -240,7 +280,7 @@ impl Either { /// assert_eq!(right.as_ref(), Right(&"some value")); /// ``` pub fn as_ref(&self) -> Either<&L, &R> { - map_either!(self, inner => inner) + map_both!(self, inner => inner) } /// Convert `&mut Either` to `Either<&mut L, &mut R>`. @@ -262,7 +302,7 @@ impl Either { /// assert_eq!(right, Right(123)); /// ``` pub fn as_mut(&mut self) -> Either<&mut L, &mut R> { - map_either!(self, inner => inner) + map_both!(self, inner => inner) } /// Convert `Pin<&Either>` to `Either, Pin<&R>>`, @@ -270,7 +310,7 @@ impl Either { pub fn as_pin_ref(self: Pin<&Self>) -> Either, Pin<&R>> { // SAFETY: We can use `new_unchecked` because the `inner` parts are // guaranteed to be pinned, as they come from `self` which is pinned. - unsafe { map_either!(Pin::get_ref(self), inner => Pin::new_unchecked(inner)) } + unsafe { map_both!(Pin::get_ref(self), inner => Pin::new_unchecked(inner)) } } /// Convert `Pin<&mut Either>` to `Either, Pin<&mut R>>`, @@ -281,7 +321,7 @@ impl Either { // to be pinned, as they come from `self` which is pinned, and we never // offer an unpinned `&mut L` or `&mut R` through `Pin<&mut Self>`. We // also don't have an implementation of `Drop`, nor manual `Unpin`. - unsafe { map_either!(Pin::get_unchecked_mut(self), inner => Pin::new_unchecked(inner)) } + unsafe { map_both!(Pin::get_unchecked_mut(self), inner => Pin::new_unchecked(inner)) } } /// Convert `Either` to `Either`. @@ -523,7 +563,7 @@ impl Either { L: IntoIterator, R: IntoIterator, { - map_either!(self, inner => inner.into_iter()) + map_both!(self, inner => inner.into_iter()) } /// Borrow the inner value as an iterator. @@ -546,7 +586,7 @@ impl Either { for<'a> &'a L: IntoIterator, for<'a> &'a R: IntoIterator::Item>, { - map_either!(self, inner => inner.into_iter()) + map_both!(self, inner => inner.into_iter()) } /// Mutably borrow the inner value as an iterator. @@ -577,7 +617,7 @@ impl Either { for<'a> &'a mut L: IntoIterator, for<'a> &'a mut R: IntoIterator::Item>, { - map_either!(self, inner => inner.into_iter()) + map_both!(self, inner => inner.into_iter()) } /// Converts an `Either` of `Iterator`s to be an `Iterator` of `Either`s @@ -599,7 +639,7 @@ impl Either { L: IntoIterator, R: IntoIterator, { - IterEither::new(map_either!(self, inner => inner.into_iter())) + IterEither::new(map_both!(self, inner => inner.into_iter())) } /// Borrows an `Either` of `Iterator`s to be an `Iterator` of `Either`s @@ -623,7 +663,7 @@ impl Either { for<'a> &'a L: IntoIterator, for<'a> &'a R: IntoIterator, { - IterEither::new(map_either!(self, inner => inner.into_iter())) + IterEither::new(map_both!(self, inner => inner.into_iter())) } /// Mutably borrows an `Either` of `Iterator`s to be an `Iterator` of `Either`s @@ -649,7 +689,7 @@ impl Either { for<'a> &'a mut L: IntoIterator, for<'a> &'a mut R: IntoIterator, { - IterEither::new(map_either!(self, inner => inner.into_iter())) + IterEither::new(map_both!(self, inner => inner.into_iter())) } /// Return left value or given value @@ -1066,7 +1106,7 @@ impl Either { where F: FnOnce(T) -> M, { - map_either!(self, t => f(t)) + map_both!(self, t => f(t)) } } @@ -1078,7 +1118,7 @@ impl Either<&L, &R> { L: Clone, R: Clone, { - map_either!(self, inner => inner.clone()) + map_both!(self, inner => inner.clone()) } /// Maps an `Either<&L, &R>` to an `Either` by copying the contents of @@ -1088,7 +1128,7 @@ impl Either<&L, &R> { L: Copy, R: Copy, { - map_either!(self, inner => *inner) + map_both!(self, inner => *inner) } } @@ -1100,7 +1140,7 @@ impl Either<&mut L, &mut R> { L: Clone, R: Clone, { - map_either!(self, inner => inner.clone()) + map_both!(self, inner => inner.clone()) } /// Maps an `Either<&mut L, &mut R>` to an `Either` by copying the contents of @@ -1110,7 +1150,7 @@ impl Either<&mut L, &mut R> { L: Copy, R: Copy, { - map_either!(self, inner => *inner) + map_both!(self, inner => *inner) } }