std: Add ToEither/IntoEither/AsEither

This commit is contained in:
Erick Tryzelaar 2013-09-11 09:33:45 -07:00
parent 12e0d7ecf0
commit e03d60e9eb
3 changed files with 162 additions and 21 deletions

View File

@ -105,6 +105,24 @@ impl<L, R> Either<L, R> {
}
}
/// A generic trait for converting a value to a `Either`
pub trait ToEither<L, R> {
/// Convert to the `either` type
fn to_either(&self) -> Either<L, R>;
}
/// A generic trait for converting a value to a `Either`
pub trait IntoEither<L, R> {
/// Convert to the `either` type
fn into_either(self) -> Either<L, R>;
}
/// A generic trait for converting a value to a `Either`
pub trait AsEither<L, R> {
/// Convert to the `either` type
fn as_either<'a>(&'a self) -> Either<&'a L, &'a R>;
}
impl<L, R: Clone> option::ToOption<R> for Either<L, R> {
#[inline]
fn to_option(&self)-> option::Option<R> {
@ -165,6 +183,23 @@ impl<L, R> result::AsResult<R, L> for Either<L, R> {
}
}
impl<L: Clone, R: Clone> ToEither<L, R> for Either<L, R> {
fn to_either(&self) -> Either<L, R> { self.clone() }
}
impl<L, R> IntoEither<L, R> for Either<L, R> {
fn into_either(self) -> Either<L, R> { self }
}
impl<L, R> AsEither<L, R> for Either<L, R> {
fn as_either<'a>(&'a self) -> Either<&'a L, &'a R> {
match *self {
Left(ref l) => Left(l),
Right(ref r) => Right(r),
}
}
}
/// An iterator yielding the `Left` values of its source
pub type Lefts<L, R, Iter> = FilterMap<'static, Either<L, R>, L, Iter>;
@ -370,4 +405,31 @@ mod tests {
let x = 404;
assert_eq!(left.as_result(), result::Err(&x));
}
#[test]
pub fn test_to_either() {
let right: Either<int, int> = Right(100);
let left: Either<int, int> = Left(404);
assert_eq!(right.to_either(), Right(100));
assert_eq!(left.to_either(), Left(404));
}
#[test]
pub fn test_into_either() {
let right: Either<int, int> = Right(100);
let left: Either<int, int> = Left(404);
assert_eq!(right.into_either(), Right(100));
assert_eq!(left.into_either(), Left(404));
}
#[test]
pub fn test_as_either() {
let right: Either<int, int> = Right(100);
let left: Either<int, int> = Left(404);
assert_eq!(right.as_either().unwrap_right(), &100);
assert_eq!(left.as_either().unwrap_left(), &404);
}
}

View File

@ -44,6 +44,7 @@ let unwrapped_msg = match msg {
use clone::Clone;
use cmp::{Eq,Ord};
use default::Default;
use either;
use util;
use num::Zero;
use iter;
@ -447,6 +448,26 @@ impl<T> result::IntoResult<T, ()> for Option<T> {
}
}
impl<T: Clone> either::ToEither<(), T> for Option<T> {
#[inline]
fn to_either(&self) -> either::Either<(), T> {
match *self {
Some(ref x) => either::Right(x.clone()),
None => either::Left(()),
}
}
}
impl<T> either::IntoEither<(), T> for Option<T> {
#[inline]
fn into_either(self) -> either::Either<(), T> {
match self {
Some(x) => either::Right(x),
None => either::Left(()),
}
}
}
impl<T: Default> Option<T> {
/// Returns the contained value or default (for this type)
#[inline]
@ -529,6 +550,9 @@ impl<A> ExactSize<A> for OptionIterator<A> {}
#[cfg(test)]
mod tests {
use super::*;
use either::{IntoEither, ToEither};
use either;
use result::{IntoResult, ToResult};
use result;
use util;
@ -817,4 +841,22 @@ mod tests {
assert_eq!(some.into_result(), result::Ok(100));
assert_eq!(none.into_result(), result::Err(()));
}
#[test]
pub fn test_to_either() {
let some: Option<int> = Some(100);
let none: Option<int> = None;
assert_eq!(some.to_either(), either::Right(100));
assert_eq!(none.to_either(), either::Left(()));
}
#[test]
pub fn test_into_either() {
let some: Option<int> = Some(100);
let none: Option<int> = None;
assert_eq!(some.into_either(), either::Right(100));
assert_eq!(none.into_either(), either::Left(()));
}
}

View File

@ -37,18 +37,6 @@ pub enum Result<T, E> {
}
impl<T, E: ToStr> Result<T, E> {
/// Convert to the `either` type
///
/// `Ok` result variants are converted to `either::Right` variants, `Err`
/// result variants are converted to `either::Left`.
#[inline]
pub fn to_either(self)-> either::Either<E, T>{
match self {
Ok(t) => either::Right(t),
Err(e) => either::Left(e),
}
}
/// Get a reference to the value out of a successful result
///
/// # Failure
@ -324,6 +312,36 @@ impl<T, E> AsResult<T, E> for Result<T, E> {
}
}
impl<T: Clone, E: Clone> either::ToEither<E, T> for Result<T, E> {
#[inline]
fn to_either(&self)-> either::Either<E, T> {
match *self {
Ok(ref t) => either::Right(t.clone()),
Err(ref e) => either::Left(e.clone()),
}
}
}
impl<T, E> either::IntoEither<E, T> for Result<T, E> {
#[inline]
fn into_either(self)-> either::Either<E, T> {
match self {
Ok(t) => either::Right(t),
Err(e) => either::Left(e),
}
}
}
impl<T, E> either::AsEither<E, T> for Result<T, E> {
#[inline]
fn as_either<'a>(&'a self)-> either::Either<&'a E, &'a T> {
match *self {
Ok(ref t) => either::Right(t),
Err(ref e) => either::Left(e),
}
}
}
#[inline]
#[allow(missing_doc)]
pub fn map_opt<T, U: ToStr, V>(o_t: &Option<T>,
@ -403,6 +421,7 @@ pub fn fold_<T, E, Iter: Iterator<Result<T, E>>>(
mod tests {
use super::*;
use either::{IntoEither, ToEither, AsEither};
use either;
use iter::range;
use option::{IntoOption, ToOption, AsOption};
@ -483,15 +502,6 @@ mod tests {
assert_eq!(*foo.get_ref(), 100);
}
#[test]
pub fn test_to_either() {
let r: Result<int, ()> = Ok(100);
let err: Result<(), int> = Err(404);
assert_eq!(r.to_either(), either::Right(100));
assert_eq!(err.to_either(), either::Left(404));
}
#[test]
fn test_collect() {
assert_eq!(collect(range(0, 0)
@ -588,4 +598,31 @@ mod tests {
let x = 404;
assert_eq!(err.as_result(), Err(&x));
}
#[test]
pub fn test_to_either() {
let ok: Result<int, int> = Ok(100);
let err: Result<int, int> = Err(404);
assert_eq!(ok.to_either(), either::Right(100));
assert_eq!(err.to_either(), either::Left(404));
}
#[test]
pub fn test_into_either() {
let ok: Result<int, int> = Ok(100);
let err: Result<int, int> = Err(404);
assert_eq!(ok.into_either(), either::Right(100));
assert_eq!(err.into_either(), either::Left(404));
}
#[test]
pub fn test_as_either() {
let ok: Result<int, int> = Ok(100);
let err: Result<int, int> = Err(404);
assert_eq!(ok.as_either().unwrap_right(), &100);
assert_eq!(err.as_either().unwrap_left(), &404);
}
}