summary refs log tree commit diff
path: root/src/libcore/option.rs
blob: 748683121d5b92c71f90b7a39c102963cefe480c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#[doc = "
Operations on the ubiquitous `option` type.

Type `option` represents an optional value.

Every `option<T>` value can either be `some(T)` or `none`. Where in other
languages you might use a nullable type, in Rust you would use an option type.
"];

#[doc = "The option type"]
enum option<T> {
    none,
    some(T),
}

pure fn get<T: copy>(opt: option<T>) -> T {
    #[doc = "
    Gets the value out of an option

    # Failure

    Fails if the value equals `none`
    "];

    alt opt { some(x) { ret x; } none { fail "option none"; } }
}

fn map<T, U: copy>(opt: option<T>, f: fn(T) -> U) -> option<U> {
    #[doc = "Maps a `some` value from one type to another"];

    alt opt { some(x) { some(f(x)) } none { none } }
}

fn chain<T, U>(opt: option<T>, f: fn(T) -> option<U>) -> option<U> {
    #[doc = "
    Update an optional value by optionally running its content through a
    function that returns an option.
    "];

    alt opt { some(x) { f(x) } none { none } }
}

pure fn is_none<T>(opt: option<T>) -> bool {
    #[doc = "Returns true if the option equals `none`"];

    alt opt { none { true } some(_) { false } }
}

pure fn is_some<T>(opt: option<T>) -> bool {
    #[doc = "Returns true if the option contains some value"];

    !is_none(opt)
}

pure fn from_maybe<T: copy>(opt: option<T>, def: T) -> T {
    #[doc = "Returns the contained value or a default"];

    alt opt { some(x) { x } none { def } }
}

fn maybe<T, U: copy>(opt: option<T>, def: U, f: fn(T) -> U) -> U {
    #[doc = "Applies a function to the contained value or returns a default"];

    alt opt { none { def } some(t) { f(t) } }
}

fn may<T>(opt: option<T>, f: fn(T)) {
    #[doc = "Performs an operation on the contained value or does nothing"];

    alt opt { none { } some(t) { f(t); } }
}

fn unwrap<T>(-opt: option<T>) -> T unsafe {
    #[doc = "
    Moves a value out of an option type and returns it.

    Useful primarily for getting strings, vectors and unique pointers out of
    option types without copying them.
    "];

    let addr = alt opt {
      some(x) { ptr::addr_of(x) }
      none { fail "option none" }
    };
    let liberated_value = unsafe::reinterpret_cast(*addr);
    unsafe::forget(opt);
    ret liberated_value;
}

#[test]
fn test_unwrap_ptr() {
    let x = ~0;
    let addr_x = ptr::addr_of(*x);
    let opt = some(x);
    let y = unwrap(opt);
    let addr_y = ptr::addr_of(*y);
    assert addr_x == addr_y;
}

#[test]
fn test_unwrap_str() {
    let x = "test";
    let addr_x = str::as_buf(x) {|buf| ptr::addr_of(buf) };
    let opt = some(x);
    let y = unwrap(opt);
    let addr_y = str::as_buf(y) {|buf| ptr::addr_of(buf) };
    assert addr_x == addr_y;
}

#[test]
fn test_unwrap_resource() {
    resource r(i: @mut int) {
        *i += 1;
    }
    let i = @mut 0;
    {
        let x = r(i);
        let opt = some(x);
        let _y = unwrap(opt);
    }
    assert *i == 1;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End: