2012-12-10 17:44:02 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
//! A type that represents one of two alternatives
|
2011-12-13 18:25:51 -06:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
#[allow(missing_doc)];
|
|
|
|
|
2013-05-12 19:34:15 -05:00
|
|
|
use container::Container;
|
2013-01-08 21:29:16 -06:00
|
|
|
use cmp::Eq;
|
2013-01-08 21:37:25 -06:00
|
|
|
use kinds::Copy;
|
2013-06-21 07:29:53 -05:00
|
|
|
use iterator::IteratorUtil;
|
2013-01-08 21:29:16 -06:00
|
|
|
use result::Result;
|
2013-01-08 21:37:25 -06:00
|
|
|
use result;
|
2012-12-23 16:41:37 -06:00
|
|
|
use vec;
|
2013-06-21 07:29:53 -05:00
|
|
|
use vec::{OwnedVector, ImmutableVector};
|
2012-03-16 17:14:37 -05:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// The either type
|
2013-03-22 14:33:53 -05:00
|
|
|
#[deriving(Clone, Eq)]
|
2012-10-01 18:11:02 -05:00
|
|
|
pub enum Either<T, U> {
|
2012-08-14 18:54:13 -05:00
|
|
|
Left(T),
|
|
|
|
Right(U)
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
|
2013-05-18 01:50:23 -05:00
|
|
|
/// Applies a function based on the given either value
|
|
|
|
///
|
|
|
|
/// If `value` is left(T) then `f_left` is applied to its contents, if
|
|
|
|
/// `value` is right(U) then `f_right` is applied to its contents, and the
|
|
|
|
/// result is returned.
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-03-07 16:38:38 -06:00
|
|
|
pub fn either<T, U, V>(f_left: &fn(&T) -> V,
|
|
|
|
f_right: &fn(&U) -> V, value: &Either<T, U>) -> V {
|
2012-08-13 19:11:33 -05:00
|
|
|
match *value {
|
2013-05-18 01:52:11 -05:00
|
|
|
Left(ref l) => f_left(l),
|
|
|
|
Right(ref r) => f_right(r)
|
2012-08-03 21:59:04 -05:00
|
|
|
}
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
|
2013-05-18 01:50:23 -05:00
|
|
|
/// Extracts from a vector of either all the left values
|
2013-02-20 19:07:17 -06:00
|
|
|
pub fn lefts<T:Copy,U>(eithers: &[Either<T, U>]) -> ~[T] {
|
2012-09-26 19:33:34 -05:00
|
|
|
do vec::build_sized(eithers.len()) |push| {
|
2013-06-21 07:29:53 -05:00
|
|
|
for eithers.iter().advance |elt| {
|
2012-09-26 19:33:34 -05:00
|
|
|
match *elt {
|
2013-06-15 19:26:59 -05:00
|
|
|
Left(ref l) => { push(copy *l); }
|
2012-09-26 19:33:34 -05:00
|
|
|
_ => { /* fallthrough */ }
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
}
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-18 01:50:23 -05:00
|
|
|
/// Extracts from a vector of either all the right values
|
2012-10-01 18:11:02 -05:00
|
|
|
pub fn rights<T, U: Copy>(eithers: &[Either<T, U>]) -> ~[U] {
|
2012-09-26 19:33:34 -05:00
|
|
|
do vec::build_sized(eithers.len()) |push| {
|
2013-06-21 07:29:53 -05:00
|
|
|
for eithers.iter().advance |elt| {
|
2012-09-26 19:33:34 -05:00
|
|
|
match *elt {
|
2013-06-15 19:26:59 -05:00
|
|
|
Right(ref r) => { push(copy *r); }
|
2012-09-26 19:33:34 -05:00
|
|
|
_ => { /* fallthrough */ }
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
}
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-18 01:50:23 -05:00
|
|
|
/// Extracts from a vector of either all the left values and right values
|
|
|
|
///
|
|
|
|
/// Returns a structure containing a vector of left values and a vector of
|
|
|
|
/// right values.
|
|
|
|
pub fn partition<T, U>(eithers: ~[Either<T, U>]) -> (~[T], ~[U]) {
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut lefts: ~[T] = ~[];
|
|
|
|
let mut rights: ~[U] = ~[];
|
2013-01-04 02:47:21 -06:00
|
|
|
do vec::consume(eithers) |_i, elt| {
|
|
|
|
match elt {
|
2013-05-18 01:52:11 -05:00
|
|
|
Left(l) => lefts.push(l),
|
|
|
|
Right(r) => rights.push(r)
|
2012-06-27 17:21:50 -05:00
|
|
|
}
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
2013-02-15 02:51:28 -06:00
|
|
|
return (lefts, rights);
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
|
2013-05-18 01:50:23 -05:00
|
|
|
/// Flips between left and right of a given either
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn flip<T, U>(eith: Either<T, U>) -> Either<U, T> {
|
2013-01-04 02:47:21 -06:00
|
|
|
match eith {
|
2013-05-18 01:52:11 -05:00
|
|
|
Right(r) => Left(r),
|
|
|
|
Left(l) => Right(l)
|
2011-12-16 09:31:35 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-18 01:50:23 -05:00
|
|
|
/// Converts either::t to a result::t
|
|
|
|
///
|
|
|
|
/// Converts an `either` type to a `result` type, making the "right" choice
|
|
|
|
/// an ok result, and the "left" choice a fail
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-18 01:50:23 -05:00
|
|
|
pub fn to_result<T, U>(eith: Either<T, U>) -> Result<U, T> {
|
2013-01-04 02:47:21 -06:00
|
|
|
match eith {
|
2013-05-18 01:52:11 -05:00
|
|
|
Right(r) => result::Ok(r),
|
|
|
|
Left(l) => result::Err(l)
|
2011-12-16 09:31:35 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-18 01:50:23 -05:00
|
|
|
/// Checks whether the given value is a left
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn is_left<T, U>(eith: &Either<T, U>) -> bool {
|
2013-05-18 01:52:11 -05:00
|
|
|
match *eith {
|
|
|
|
Left(_) => true,
|
|
|
|
_ => false
|
|
|
|
}
|
2012-01-04 09:36:53 -06:00
|
|
|
}
|
|
|
|
|
2013-05-18 01:50:23 -05:00
|
|
|
/// Checks whether the given value is a right
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn is_right<T, U>(eith: &Either<T, U>) -> bool {
|
2013-05-18 01:52:11 -05:00
|
|
|
match *eith {
|
|
|
|
Right(_) => true,
|
|
|
|
_ => false
|
|
|
|
}
|
2012-01-04 09:36:53 -06:00
|
|
|
}
|
|
|
|
|
2013-05-18 01:50:23 -05:00
|
|
|
/// Retrieves the value in the left branch. Fails if the either is Right.
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn unwrap_left<T,U>(eith: Either<T,U>) -> T {
|
2013-02-15 02:51:28 -06:00
|
|
|
match eith {
|
|
|
|
Left(x) => x,
|
2013-05-05 17:18:51 -05:00
|
|
|
Right(_) => fail!("either::unwrap_left Right")
|
2012-08-24 20:08:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-18 01:50:23 -05:00
|
|
|
/// Retrieves the value in the right branch. Fails if the either is Left.
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn unwrap_right<T,U>(eith: Either<T,U>) -> U {
|
2013-02-15 02:51:28 -06:00
|
|
|
match eith {
|
|
|
|
Right(x) => x,
|
2013-05-05 17:18:51 -05:00
|
|
|
Left(_) => fail!("either::unwrap_right Left")
|
2012-08-24 20:08:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl<T, U> Either<T, U> {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn either<V>(&self, f_left: &fn(&T) -> V, f_right: &fn(&U) -> V) -> V {
|
2013-02-01 18:37:38 -06:00
|
|
|
either(f_left, f_right, self)
|
|
|
|
}
|
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn flip(self) -> Either<U, T> { flip(self) }
|
2013-02-01 18:37:38 -06:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn to_result(self) -> Result<U, T> { to_result(self) }
|
2013-02-01 18:37:38 -06:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn is_left(&self) -> bool { is_left(self) }
|
2013-02-01 18:37:38 -06:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn is_right(&self) -> bool { is_right(self) }
|
2013-02-01 18:37:38 -06:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn unwrap_left(self) -> T { unwrap_left(self) }
|
2012-12-18 20:54:25 -06:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn unwrap_right(self) -> U { unwrap_right(self) }
|
2012-12-18 20:54:25 -06:00
|
|
|
}
|
|
|
|
|
2012-01-17 19:28:21 -06:00
|
|
|
#[test]
|
|
|
|
fn test_either_left() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let val = Left(10);
|
2012-08-13 19:11:33 -05:00
|
|
|
fn f_left(x: &int) -> bool { *x == 10 }
|
|
|
|
fn f_right(_x: &uint) -> bool { false }
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!((either(f_left, f_right, &val)));
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_either_right() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let val = Right(10u);
|
2012-08-13 19:11:33 -05:00
|
|
|
fn f_left(_x: &int) -> bool { false }
|
|
|
|
fn f_right(x: &uint) -> bool { *x == 10u }
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!((either(f_left, f_right, &val)));
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_lefts() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = lefts(input);
|
2013-03-13 17:30:37 -05:00
|
|
|
assert_eq!(result, ~[10, 12, 14]);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_lefts_none() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[Right(10), Right(10)];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = lefts(input);
|
2013-05-14 04:52:12 -05:00
|
|
|
assert_eq!(result.len(), 0u);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_lefts_empty() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = lefts(input);
|
2013-05-14 04:52:12 -05:00
|
|
|
assert_eq!(result.len(), 0u);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_rights() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = rights(input);
|
2013-03-13 17:30:37 -05:00
|
|
|
assert_eq!(result, ~[11, 13]);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_rights_none() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[Left(10), Left(10)];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = rights(input);
|
2013-05-14 04:52:12 -05:00
|
|
|
assert_eq!(result.len(), 0u);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_rights_empty() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = rights(input);
|
2013-05-14 04:52:12 -05:00
|
|
|
assert_eq!(result.len(), 0u);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_partition() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
|
2012-11-26 22:05:19 -06:00
|
|
|
let (lefts, rights) = partition(input);
|
2013-03-13 17:30:37 -05:00
|
|
|
assert_eq!(lefts[0], 10);
|
|
|
|
assert_eq!(lefts[1], 12);
|
|
|
|
assert_eq!(lefts[2], 14);
|
|
|
|
assert_eq!(rights[0], 11);
|
|
|
|
assert_eq!(rights[1], 13);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_partition_no_lefts() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[Right(10), Right(11)];
|
2012-11-26 22:05:19 -06:00
|
|
|
let (lefts, rights) = partition(input);
|
2013-05-14 04:52:12 -05:00
|
|
|
assert_eq!(lefts.len(), 0u);
|
|
|
|
assert_eq!(rights.len(), 2u);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_partition_no_rights() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[Left(10), Left(11)];
|
2012-11-26 22:05:19 -06:00
|
|
|
let (lefts, rights) = partition(input);
|
2013-05-14 04:52:12 -05:00
|
|
|
assert_eq!(lefts.len(), 2u);
|
|
|
|
assert_eq!(rights.len(), 0u);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_partition_empty() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[];
|
2012-11-26 22:05:19 -06:00
|
|
|
let (lefts, rights) = partition(input);
|
2013-05-14 04:52:12 -05:00
|
|
|
assert_eq!(lefts.len(), 0u);
|
|
|
|
assert_eq!(rights.len(), 0u);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|