diff options
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 441 |
1 files changed, 383 insertions, 58 deletions
@@ -13,13 +13,10 @@ //! #![doc(html_root_url = "https://docs.rs/either/1/")] -#![cfg_attr(all(not(test), not(feature = "use_std")), no_std)] -#[cfg(all(not(test), not(feature = "use_std")))] -extern crate core as std; +#![no_std] -#[cfg(feature = "serde")] -#[macro_use] -extern crate serde; +#[cfg(any(test, feature = "use_std"))] +extern crate std; #[cfg(feature = "serde")] pub mod serde_untagged; @@ -27,18 +24,20 @@ pub mod serde_untagged; #[cfg(feature = "serde")] pub mod serde_untagged_optional; -use std::convert::{AsMut, AsRef}; -use std::fmt; -use std::iter; -use std::ops::Deref; -use std::ops::DerefMut; +use core::convert::{AsMut, AsRef}; +use core::fmt; +use core::future::Future; +use core::iter; +use core::ops::Deref; +use core::ops::DerefMut; +use core::pin::Pin; #[cfg(any(test, feature = "use_std"))] use std::error::Error; #[cfg(any(test, feature = "use_std"))] -use std::io::{self, BufRead, Read, Write}; +use std::io::{self, BufRead, Read, Seek, SeekFrom, Write}; -pub use Either::{Left, Right}; +pub use crate::Either::{Left, Right}; /// The enum `Either` with variants `Left` and `Right` is a general purpose /// sum type with two cases. @@ -46,8 +45,8 @@ pub use Either::{Left, Right}; /// The `Either` type is symmetric and treats its variants the same way, without /// preference. /// (For representing success or error, use the regular `Result` enum instead.) -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub enum Either<L, R> { /// A value of type `L`. Left(L), @@ -55,11 +54,36 @@ pub enum Either<L, R> { Right(R), } -macro_rules! either { +/// Evaluate the provided expression for both [`Either::Left`] and [`Either::Right`]. +/// +/// 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::for_both!(` *expression* `,` *pattern* `=>` *expression* `)` +/// +/// # Example +/// +/// ``` +/// use either::Either; +/// +/// fn length(owned_or_borrowed: Either<String, &'static str>) -> usize { +/// either::for_both!(owned_or_borrowed, s => s.len()) +/// } +/// +/// fn main() { +/// let borrowed = Either::Right("Hello world!"); +/// let owned = Either::Left("Hello world!".to_owned()); +/// +/// assert_eq!(length(borrowed), 12); +/// assert_eq!(length(owned), 12); +/// } +/// ``` +#[macro_export] +macro_rules! for_both { ($value:expr, $pattern:pat => $result:expr) => { match $value { - Either::Left($pattern) => $result, - Either::Right($pattern) => $result, + $crate::Either::Left($pattern) => $result, + $crate::Either::Right($pattern) => $result, } }; } @@ -74,11 +98,10 @@ macro_rules! either { /// # Example /// /// ``` -/// #[macro_use] extern crate either; /// use either::{Either, Left, Right}; /// /// fn twice(wrapper: Either<u32, &str>) -> Either<u32, &str> { -/// let value = try_left!(wrapper); +/// let value = either::try_left!(wrapper); /// Left(value * 2) /// } /// @@ -92,7 +115,7 @@ macro_rules! try_left { ($expr:expr) => { match $expr { $crate::Left(val) => val, - $crate::Right(err) => return $crate::Right(::std::convert::From::from(err)), + $crate::Right(err) => return $crate::Right(::core::convert::From::from(err)), } }; } @@ -102,12 +125,29 @@ macro_rules! try_left { macro_rules! try_right { ($expr:expr) => { match $expr { - $crate::Left(err) => return $crate::Left(::std::convert::From::from(err)), + $crate::Left(err) => return $crate::Left(::core::convert::From::from(err)), $crate::Right(val) => val, } }; } +impl<L: Clone, R: Clone> Clone for Either<L, R> { + fn clone(&self) -> Self { + match self { + Left(inner) => Left(inner.clone()), + Right(inner) => Right(inner.clone()), + } + } + + fn clone_from(&mut self, source: &Self) { + match (self, source) { + (Left(dest), Left(source)) => dest.clone_from(source), + (Right(dest), Right(source)) => dest.clone_from(source), + (dest, source) => *dest = source.clone(), + } + } +} + impl<L, R> Either<L, R> { /// Return true if the value is the `Left` variant. /// @@ -217,6 +257,35 @@ impl<L, R> Either<L, R> { } } + /// Convert `Pin<&Either<L, R>>` to `Either<Pin<&L>, Pin<&R>>`, + /// pinned projections of the inner variants. + pub fn as_pin_ref(self: Pin<&Self>) -> Either<Pin<&L>, 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 { + match *Pin::get_ref(self) { + Left(ref inner) => Left(Pin::new_unchecked(inner)), + Right(ref inner) => Right(Pin::new_unchecked(inner)), + } + } + } + + /// Convert `Pin<&mut Either<L, R>>` to `Either<Pin<&mut L>, Pin<&mut R>>`, + /// pinned projections of the inner variants. + pub fn as_pin_mut(self: Pin<&mut Self>) -> Either<Pin<&mut L>, Pin<&mut R>> { + // SAFETY: `get_unchecked_mut` is fine because we don't move anything. + // We can use `new_unchecked` because the `inner` parts are guaranteed + // 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 { + match *Pin::get_unchecked_mut(self) { + Left(ref mut inner) => Left(Pin::new_unchecked(inner)), + Right(ref mut inner) => Right(Pin::new_unchecked(inner)), + } + } + } + /// Convert `Either<L, R>` to `Either<R, L>`. /// /// ``` @@ -388,6 +457,7 @@ impl<L, R> Either<L, R> { /// 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, @@ -558,7 +628,7 @@ impl<L, R> Either<L, R> { /// ``` pub fn unwrap_left(self) -> L where - R: std::fmt::Debug, + R: core::fmt::Debug, { match self { Either::Left(l) => l, @@ -589,7 +659,7 @@ impl<L, R> Either<L, R> { /// ``` pub fn unwrap_right(self) -> R where - L: std::fmt::Debug, + L: core::fmt::Debug, { match self { Either::Right(r) => r, @@ -618,7 +688,7 @@ impl<L, R> Either<L, R> { /// ``` pub fn expect_left(self, msg: &str) -> L where - R: std::fmt::Debug, + R: core::fmt::Debug, { match self { Either::Left(l) => l, @@ -647,13 +717,103 @@ impl<L, R> Either<L, R> { /// ``` pub fn expect_right(self, msg: &str) -> R where - L: std::fmt::Debug, + L: core::fmt::Debug, { match self { Either::Right(r) => r, Either::Left(l) => panic!("{}: {:?}", msg, l), } } + + /// Convert the contained value into `T` + /// + /// # Examples + /// + /// ``` + /// # use either::*; + /// // Both u16 and u32 can be converted to u64. + /// let left: Either<u16, u32> = Left(3u16); + /// assert_eq!(left.either_into::<u64>(), 3u64); + /// let right: Either<u16, u32> = Right(7u32); + /// assert_eq!(right.either_into::<u64>(), 7u64); + /// ``` + pub fn either_into<T>(self) -> T + where + L: Into<T>, + R: Into<T>, + { + match self { + Either::Left(l) => l.into(), + Either::Right(r) => r.into(), + } + } +} + +impl<L, R> Either<Option<L>, Option<R>> { + /// Factors out `None` from an `Either` of [`Option`]. + /// + /// ``` + /// use either::*; + /// let left: Either<_, Option<String>> = Left(Some(vec![0])); + /// assert_eq!(left.factor_none(), Some(Left(vec![0]))); + /// + /// let right: Either<Option<Vec<u8>>, _> = Right(Some(String::new())); + /// assert_eq!(right.factor_none(), Some(Right(String::new()))); + /// ``` + // TODO(MSRV): doc(alias) was stabilized in Rust 1.48 + // #[doc(alias = "transpose")] + pub fn factor_none(self) -> Option<Either<L, R>> { + match self { + Left(l) => l.map(Either::Left), + Right(r) => r.map(Either::Right), + } + } +} + +impl<L, R, E> Either<Result<L, E>, Result<R, E>> { + /// Factors out a homogenous type from an `Either` of [`Result`]. + /// + /// Here, the homogeneous type is the `Err` type of the [`Result`]. + /// + /// ``` + /// use either::*; + /// let left: Either<_, Result<String, u32>> = Left(Ok(vec![0])); + /// assert_eq!(left.factor_err(), Ok(Left(vec![0]))); + /// + /// let right: Either<Result<Vec<u8>, u32>, _> = Right(Ok(String::new())); + /// assert_eq!(right.factor_err(), Ok(Right(String::new()))); + /// ``` + // TODO(MSRV): doc(alias) was stabilized in Rust 1.48 + // #[doc(alias = "transpose")] + pub fn factor_err(self) -> Result<Either<L, R>, E> { + match self { + Left(l) => l.map(Either::Left), + Right(r) => r.map(Either::Right), + } + } +} + +impl<T, L, R> Either<Result<T, L>, Result<T, R>> { + /// Factors out a homogenous type from an `Either` of [`Result`]. + /// + /// Here, the homogeneous type is the `Ok` type of the [`Result`]. + /// + /// ``` + /// use either::*; + /// let left: Either<_, Result<u32, String>> = Left(Err(vec![0])); + /// assert_eq!(left.factor_ok(), Err(Left(vec![0]))); + /// + /// let right: Either<Result<u32, Vec<u8>>, _> = Right(Err(String::new())); + /// assert_eq!(right.factor_ok(), Err(Right(String::new()))); + /// ``` + // TODO(MSRV): doc(alias) was stabilized in Rust 1.48 + // #[doc(alias = "transpose")] + pub fn factor_ok(self) -> Result<T, Either<L, R>> { + match self { + Left(l) => l.map_err(Either::Left), + Right(r) => r.map_err(Either::Right), + } + } } impl<T, L, R> Either<(T, L), (T, R)> { @@ -711,7 +871,7 @@ impl<T> Either<T, T> { /// assert_eq!(right.into_inner(), 123); /// ``` pub fn into_inner(self) -> T { - either!(self, inner => inner) + for_both!(self, inner => inner) } /// Map `f` over the contained value and return the result in the @@ -747,6 +907,7 @@ impl<L, R> From<Result<R, L>> for Either<L, R> { } /// Convert from `Either` to `Result` with `Right => Ok` and `Left => Err`. +#[allow(clippy::from_over_into)] // From requires RFC 2451, Rust 1.41 impl<L, R> Into<Result<R, L>> for Either<L, R> { fn into(self) -> Result<R, L> { match self { @@ -765,7 +926,7 @@ where where T: IntoIterator<Item = A>, { - either!(*self, ref mut inner => inner.extend(iter)) + for_both!(*self, ref mut inner => inner.extend(iter)) } } @@ -778,44 +939,87 @@ where type Item = L::Item; fn next(&mut self) -> Option<Self::Item> { - either!(*self, ref mut inner => inner.next()) + for_both!(*self, ref mut inner => inner.next()) } fn size_hint(&self) -> (usize, Option<usize>) { - either!(*self, ref inner => inner.size_hint()) + for_both!(*self, ref inner => inner.size_hint()) } fn fold<Acc, G>(self, init: Acc, f: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc, { - either!(self, inner => inner.fold(init, f)) + for_both!(self, inner => inner.fold(init, f)) + } + + fn for_each<F>(self, f: F) + where + F: FnMut(Self::Item), + { + for_both!(self, inner => inner.for_each(f)) } fn count(self) -> usize { - either!(self, inner => inner.count()) + for_both!(self, inner => inner.count()) } fn last(self) -> Option<Self::Item> { - either!(self, inner => inner.last()) + for_both!(self, inner => inner.last()) } fn nth(&mut self, n: usize) -> Option<Self::Item> { - either!(*self, ref mut inner => inner.nth(n)) + for_both!(*self, ref mut inner => inner.nth(n)) } fn collect<B>(self) -> B where B: iter::FromIterator<Self::Item>, { - either!(self, inner => inner.collect()) + for_both!(self, inner => inner.collect()) + } + + fn partition<B, F>(self, f: F) -> (B, B) + where + B: Default + Extend<Self::Item>, + F: FnMut(&Self::Item) -> bool, + { + for_both!(self, inner => inner.partition(f)) } fn all<F>(&mut self, f: F) -> bool where F: FnMut(Self::Item) -> bool, { - either!(*self, ref mut inner => inner.all(f)) + for_both!(*self, ref mut inner => inner.all(f)) + } + + fn any<F>(&mut self, f: F) -> bool + where + F: FnMut(Self::Item) -> bool, + { + for_both!(*self, ref mut inner => inner.any(f)) + } + + fn find<P>(&mut self, predicate: P) -> Option<Self::Item> + where + P: FnMut(&Self::Item) -> bool, + { + for_both!(*self, ref mut inner => inner.find(predicate)) + } + + fn find_map<B, F>(&mut self, f: F) -> Option<B> + where + F: FnMut(Self::Item) -> Option<B>, + { + for_both!(*self, ref mut inner => inner.find_map(f)) + } + + fn position<P>(&mut self, predicate: P) -> Option<usize> + where + P: FnMut(Self::Item) -> bool, + { + for_both!(*self, ref mut inner => inner.position(predicate)) } } @@ -825,7 +1029,26 @@ where R: DoubleEndedIterator<Item = L::Item>, { fn next_back(&mut self) -> Option<Self::Item> { - either!(*self, ref mut inner => inner.next_back()) + for_both!(*self, ref mut inner => inner.next_back()) + } + + // TODO(MSRV): This was stabilized in Rust 1.37 + // fn nth_back(&mut self, n: usize) -> Option<Self::Item> { + // for_both!(*self, ref mut inner => inner.nth_back(n)) + // } + + fn rfold<Acc, G>(self, init: Acc, f: G) -> Acc + where + G: FnMut(Acc, Self::Item) -> Acc, + { + for_both!(self, inner => inner.rfold(init, f)) + } + + fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> + where + P: FnMut(&Self::Item) -> bool, + { + for_both!(*self, ref mut inner => inner.rfind(predicate)) } } @@ -834,6 +1057,32 @@ where L: ExactSizeIterator, R: ExactSizeIterator<Item = L::Item>, { + fn len(&self) -> usize { + for_both!(*self, ref inner => inner.len()) + } +} + +impl<L, R> iter::FusedIterator for Either<L, R> +where + L: iter::FusedIterator, + R: iter::FusedIterator<Item = L::Item>, +{ +} + +/// `Either<L, R>` is a future if both `L` and `R` are futures. +impl<L, R> Future for Either<L, R> +where + L: Future, + R: Future<Output = L::Output>, +{ + type Output = L::Output; + + fn poll( + self: Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll<Self::Output> { + for_both!(self.as_pin_mut(), inner => inner.poll(cx)) + } } #[cfg(any(test, feature = "use_std"))] @@ -846,11 +1095,33 @@ where R: Read, { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - either!(*self, ref mut inner => inner.read(buf)) + for_both!(*self, ref mut inner => inner.read(buf)) } - fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { - either!(*self, ref mut inner => inner.read_to_end(buf)) + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + for_both!(*self, ref mut inner => inner.read_exact(buf)) + } + + fn read_to_end(&mut self, buf: &mut std::vec::Vec<u8>) -> io::Result<usize> { + for_both!(*self, ref mut inner => inner.read_to_end(buf)) + } + + fn read_to_string(&mut self, buf: &mut std::string::String) -> io::Result<usize> { + for_both!(*self, ref mut inner => inner.read_to_string(buf)) + } +} + +#[cfg(any(test, feature = "use_std"))] +/// `Either<L, R>` implements `Seek` if both `L` and `R` do. +/// +/// Requires crate feature `"use_std"` +impl<L, R> Seek for Either<L, R> +where + L: Seek, + R: Seek, +{ + fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { + for_both!(*self, ref mut inner => inner.seek(pos)) } } @@ -862,11 +1133,19 @@ where R: BufRead, { fn fill_buf(&mut self) -> io::Result<&[u8]> { - either!(*self, ref mut inner => inner.fill_buf()) + for_both!(*self, ref mut inner => inner.fill_buf()) } fn consume(&mut self, amt: usize) { - either!(*self, ref mut inner => inner.consume(amt)) + for_both!(*self, ref mut inner => inner.consume(amt)) + } + + fn read_until(&mut self, byte: u8, buf: &mut std::vec::Vec<u8>) -> io::Result<usize> { + for_both!(*self, ref mut inner => inner.read_until(byte, buf)) + } + + fn read_line(&mut self, buf: &mut std::string::String) -> io::Result<usize> { + for_both!(*self, ref mut inner => inner.read_line(buf)) } } @@ -880,11 +1159,19 @@ where R: Write, { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - either!(*self, ref mut inner => inner.write(buf)) + for_both!(*self, ref mut inner => inner.write(buf)) + } + + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + for_both!(*self, ref mut inner => inner.write_all(buf)) + } + + fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> { + for_both!(*self, ref mut inner => inner.write_fmt(fmt)) } fn flush(&mut self) -> io::Result<()> { - either!(*self, ref mut inner => inner.flush()) + for_both!(*self, ref mut inner => inner.flush()) } } @@ -894,7 +1181,7 @@ where R: AsRef<Target>, { fn as_ref(&self) -> &Target { - either!(*self, ref inner => inner.as_ref()) + for_both!(*self, ref inner => inner.as_ref()) } } @@ -905,7 +1192,7 @@ macro_rules! impl_specific_ref_and_mut { where L: AsRef<$t>, R: AsRef<$t> { fn as_ref(&self) -> &$t { - either!(*self, ref inner => inner.as_ref()) + for_both!(*self, ref inner => inner.as_ref()) } } @@ -914,7 +1201,7 @@ macro_rules! impl_specific_ref_and_mut { where L: AsMut<$t>, R: AsMut<$t> { fn as_mut(&mut self) -> &mut $t { - either!(*self, ref mut inner => inner.as_mut()) + for_both!(*self, ref mut inner => inner.as_mut()) } } }; @@ -943,7 +1230,7 @@ where R: AsRef<[Target]>, { fn as_ref(&self) -> &[Target] { - either!(*self, ref inner => inner.as_ref()) + for_both!(*self, ref inner => inner.as_ref()) } } @@ -953,7 +1240,7 @@ where R: AsMut<Target>, { fn as_mut(&mut self) -> &mut Target { - either!(*self, ref mut inner => inner.as_mut()) + for_both!(*self, ref mut inner => inner.as_mut()) } } @@ -963,7 +1250,7 @@ where R: AsMut<[Target]>, { fn as_mut(&mut self) -> &mut [Target] { - either!(*self, ref mut inner => inner.as_mut()) + for_both!(*self, ref mut inner => inner.as_mut()) } } @@ -975,7 +1262,7 @@ where type Target = L::Target; fn deref(&self) -> &Self::Target { - either!(*self, ref inner => &*inner) + for_both!(*self, ref inner => &**inner) } } @@ -985,7 +1272,7 @@ where R: DerefMut<Target = L::Target>, { fn deref_mut(&mut self) -> &mut Self::Target { - either!(*self, ref mut inner => &mut *inner) + for_both!(*self, ref mut inner => &mut *inner) } } @@ -996,15 +1283,18 @@ where L: Error, R: Error, { + fn source(&self) -> Option<&(dyn Error + 'static)> { + for_both!(*self, ref inner => inner.source()) + } + #[allow(deprecated)] fn description(&self) -> &str { - either!(*self, ref inner => inner.description()) + for_both!(*self, ref inner => inner.description()) } #[allow(deprecated)] - #[allow(unknown_lints, bare_trait_objects)] - fn cause(&self) -> Option<&Error> { - either!(*self, ref inner => inner.cause()) + fn cause(&self) -> Option<&dyn Error> { + for_both!(*self, ref inner => inner.cause()) } } @@ -1013,8 +1303,8 @@ where L: fmt::Display, R: fmt::Display, { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - either!(*self, ref inner => inner.fmt(f)) + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for_both!(*self, ref inner => inner.fmt(f)) } } @@ -1033,6 +1323,8 @@ fn basic() { #[test] fn macros() { + use std::string::String; + fn a() -> Either<u32, u32> { let x: u32 = try_left!(Right(1337u32)); Left(x * 2) @@ -1047,6 +1339,8 @@ fn macros() { #[test] fn deref() { + use std::string::String; + fn is_str(_: &str) {} let value: Either<String, &str> = Left(String::from("test")); is_str(&*value); @@ -1065,6 +1359,37 @@ fn iter() { } #[test] +fn seek() { + use std::io; + + let use_empty = false; + let mut mockdata = [0x00; 256]; + for i in 0..256 { + mockdata[i] = i as u8; + } + + let mut reader = if use_empty { + // Empty didn't impl Seek until Rust 1.51 + Left(io::Cursor::new([])) + } else { + Right(io::Cursor::new(&mockdata[..])) + }; + + let mut buf = [0u8; 16]; + assert_eq!(reader.read(&mut buf).unwrap(), buf.len()); + assert_eq!(buf, mockdata[..buf.len()]); + + // the first read should advance the cursor and return the next 16 bytes thus the `ne` + assert_eq!(reader.read(&mut buf).unwrap(), buf.len()); + assert_ne!(buf, mockdata[..buf.len()]); + + // if the seek operation fails it should read 16..31 instead of 0..15 + reader.seek(io::SeekFrom::Start(0)).unwrap(); + assert_eq!(reader.read(&mut buf).unwrap(), buf.len()); + assert_eq!(buf, mockdata[..buf.len()]); +} + +#[test] fn read_write() { use std::io; |