result.rs 2.3 KB
Newer Older
B
Brian Anderson 已提交
1
#[doc = "A type representing either success or failure"];
2

B
Brian Anderson 已提交
3
#[doc = "The result type"]
P
Patrick Walton 已提交
4
enum t<T, U> {
B
Brian Anderson 已提交
5
    #[doc = "Contains the successful result value"]
6
    ok(T),
B
Brian Anderson 已提交
7
    #[doc = "Contains the error value"]
8
    err(U)
9 10
}

B
Brian Anderson 已提交
11
#[doc = "
12 13
Get the value out of a successful result

B
Brian Anderson 已提交
14
# Failure
15 16

If the result is an error
B
Brian Anderson 已提交
17
"]
18
fn get<T: copy, U>(res: t<T, U>) -> T {
19 20 21 22
    alt res {
      ok(t) { t }
      err(_) {
        // FIXME: Serialize the error value
23
        // and include it in the fail message (maybe just note it)
24 25 26 27 28
        fail "get called on error result";
      }
    }
}

B
Brian Anderson 已提交
29
#[doc = "
30 31
Get the value out of an error result

B
Brian Anderson 已提交
32
# Failure
33 34

If the result is not an error
B
Brian Anderson 已提交
35
"]
36
fn get_err<T, U: copy>(res: t<T, U>) -> U {
37 38 39 40 41 42 43 44
    alt res {
      err(u) { u }
      ok(_) {
        fail "get_error called on ok result";
      }
    }
}

B
Brian Anderson 已提交
45
#[doc = "Returns true if the result is `ok`"]
46
pure fn success<T, U>(res: t<T, U>) -> bool {
47 48 49 50 51 52
    alt res {
      ok(_) { true }
      err(_) { false }
    }
}

B
Brian Anderson 已提交
53
#[doc = "Returns true if the result is `error`"]
54
pure fn failure<T, U>(res: t<T, U>) -> bool {
55 56 57
    !success(res)
}

B
Brian Anderson 已提交
58 59 60 61 62 63
#[doc = "
Convert to the `either` type

`ok` result variants are converted to `either::right` variants, `err`
result variants are converted to `either::left`.
"]
64
pure fn to_either<T: copy, U: copy>(res: t<U, T>) -> either::t<T, U> {
65 66 67 68 69 70
    alt res {
      ok(res) { either::right(res) }
      err(fail_) { either::left(fail_) }
    }
}

B
Brian Anderson 已提交
71
#[doc = "
72 73
Call a function based on a previous result

B
Brian Anderson 已提交
74 75
If `res` is `ok` then the value is extracted and passed to `op` whereupon
`op`s result is returned. if `res` is `err` then it is immediately returned.
76 77 78 79
This function can be used to compose the results of two functions.

Example:

B
Brian Anderson 已提交
80 81 82 83
    let res = chain(read_file(file)) { |buf|
        ok(parse_buf(buf))
    }
"]
N
Niko Matsakis 已提交
84
fn chain<T, U: copy, V: copy>(res: t<T, V>, op: fn(T) -> t<U, V>)
85 86 87 88 89 90
    -> t<U, V> {
    alt res {
      ok(t) { op(t) }
      err(e) { err(e) }
    }
}
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

#[cfg(test)]
mod tests {
    fn op1() -> result::t<int, str> { result::ok(666) }

    fn op2(&&i: int) -> result::t<uint, str> { result::ok(i as uint + 1u) }

    fn op3() -> result::t<int, str> { result::err("sadface") }

    #[test]
    fn chain_success() {
        assert get(chain(op1(), op2)) == 667u;
    }

    #[test]
    fn chain_failure() {
        assert get_err(chain(op3(), op2)) == "sadface";
    }
}