pub mod environment;
pub use environment::*;
use self::Partial::*;
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
pub enum Partial<T>
{
Value(T),
Fake(T),
Nothing
}
impl<T> Partial<T>
{
pub fn unwrap(self) -> T {
match self {
Value(x) => x,
Fake(_) => panic!("called `Partial::unwrap()` on a `Fake` value"),
Nothing => panic!("called `Partial::unwrap()` on a `Nothing` value")
}
}
pub fn unwrap_all(self) -> T {
match self {
Value(x) | Fake(x) => x,
Nothing => panic!("called `Partial::unwrap_all()` on a `Nothing` value")
}
}
pub fn expect(self, msg: &str) -> T {
match self {
Value(x) => x,
Fake(_)
| Nothing => panic!("{}", msg)
}
}
pub fn ensure(self, msg: &str) -> Self {
match self {
Fake(_) | Nothing => panic!("{}", msg),
x => x
}
}
pub fn unwrap_or_else<F>(self, f: F) -> T where
F: FnOnce() -> T
{
match self {
Value(x) => x,
_ => f()
}
}
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Partial<U> {
match self {
Value(x) => Value(f(x)),
Fake(x) => Fake(f(x)),
Nothing => Nothing
}
}
pub fn and_then<U, F: FnOnce(T) -> Partial<U>>(self, f: F) -> Partial<U> {
match self {
Value(x) => f(x),
Fake(x) => match f(x) {
Value(x) => Fake(x),
x => x
},
Nothing => Nothing
}
}
pub fn and_next<U, F: FnOnce(T) -> Partial<U>>(self, f: F) -> Partial<U> {
match self {
Value(x) => f(x),
_ => Nothing
}
}
pub fn is_value(&self) -> bool {
match self {
&Partial::Value(_) => true,
_ => false
}
}
pub fn is_fake(&self) -> bool {
match self {
&Partial::Fake(_) => true,
_ => false
}
}
pub fn is_nothing(&self) -> bool {
match self {
&Partial::Nothing => true,
_ => false
}
}
}
#[cfg(test)]
mod test {
use super::*;
use super::Partial::*;
fn nothing_i32(_: i32) -> Partial<i32> {
Nothing
}
#[test]
fn partial_unwrap() {
assert_eq!(Value(9i32).unwrap(), 9i32);
assert_eq!(Value(9i32).unwrap_all(), 9i32);
assert_eq!(Fake(9i32).unwrap_all(), 9i32);
}
#[test]
#[should_panic]
fn partial_unwrap_fake() {
Fake(9i32).unwrap();
}
#[test]
#[should_panic]
fn partial_unwrap_nothing() {
let x: Partial<i32> = Nothing;
x.unwrap();
}
#[test]
#[should_panic]
fn partial_unwrap_all_nothing() {
Nothing::<i32>.unwrap_all();
}
#[test]
fn partial_unwrap_or_else() {
assert_eq!(Value(9i32).unwrap_or_else(|| 1i32), 9i32);
assert_eq!(Fake(9i32).unwrap_or_else(|| 1i32), 1i32);
assert_eq!(Nothing.unwrap_or_else(|| 1i32), 1i32);
}
#[test]
fn partial_map() {
assert_eq!(Value(9i32).map(|i|i*2), Value(18i32));
assert_eq!(Fake(9i32).map(|i|i*2), Fake(18i32));
assert_eq!(Nothing.map(|i:i32|i), Nothing);
}
#[test]
fn partial_and_then() {
assert_eq!(Value(9i32).and_then(|i| Value(i*2)), Value(18i32));
assert_eq!(Value(9i32).and_then(|i| Fake(i*2)), Fake(18i32));
assert_eq!(Fake(9i32).and_then(|i| Fake(i*2)), Fake(18i32));
assert_eq!(Fake(9i32).and_then(|i| Value(i*2)), Fake(18i32));
assert_eq!(Fake(9i32).and_then(nothing_i32), Nothing);
}
#[test]
fn partial_and_next() {
assert_eq!(Value(1i32).and_next(|i| Value(i*2)), Value(2));
assert_eq!(Value(1i32).and_next(|i| Fake(i*2)), Fake(2));
assert_eq!(Value(1i32).and_next(nothing_i32), Nothing);
assert_eq!(Fake(1i32).and_next(|i| Value(i*2)), Nothing);
assert_eq!(nothing_i32(0).and_next(|i| Value(i*2)), Nothing);
}
}