View difference between Paste ID: SU0BMXsn and ZXR6Qgie
SHOW: | | - or go back to the newest paste.
1
/*
2
This module is based on code in the std.typecons module in the standard library of the D programming language. The authors of std.typecons deserve credit and thanks, and are listed at the top of the source code for the module, which is available here:
3
4
https://github.com/D-Programming-Language/phobos/blob/master/std/typecons.d
5
6
Copyright (c) 2013, w0rp <moebiuspersona@gmail.com>
7
All rights reserved.
8
9
Redistribution and use in source and binary forms, with or without
10
modification, are permitted provided that the following conditions are met:
11
12
1. Redistributions of source code must retain the above copyright notice, this
13
   list of conditions and the following disclaimer.
14
2. Redistributions in binary form must reproduce the above copyright notice,
15
   this list of conditions and the following disclaimer in the documentation
16
   and/or other materials provided with the distribution.
17
18
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
import std.exception;
31
import std.typecons;
32
33
module option;
34
35
struct Option(T) if(is(T == class)) {
36
    private T _value;
37
38
    this(T value) {
39
        _value = value;
40
    }
41
42
    this(Nullable!T value) {
43
        if (!value.isNull)
44
        {
45
            _value = value;
46
        }
47
    }
48
49
    @property @safe const pure nothrow
50
    bool isNull() {
51
        return _value is null;
52
    }
53
54
    @safe pure nothrow
55
    void opAssign(T value) {
56
        _value = value;
57
    }
58
59
    @safe pure
60
    void opAssign(Nullable!T value) {
61
        if (!value.isNull)
62
        {
63
            _value = value;
64
        }
65
    }
66
67
    @safe pure nothrow nullify() {
68
        _value = null;
69
    }
70
71
    @property @safe pure nothrow inout(T) get() inout {
72
        enum message = "Called `get' on null Option!" ~ T.stringof ~ ".";
73
        assert(_value !is null, message);
74
        return _value;
75
    }
76
77
    alias get this;
78
}
79
80
struct Option(T) if(!is(T == class)) {
81
    private T _value;
82
    private bool _isNull = true;
83
84
    this(T value) {
85
        _value = value;
86
        _isNull = false;
87
    }
88
89
    this(Nullable!T value) {
90
        if (!value.isNull) {
91
            _value = value;
92
            _isNull = false;
93
        }
94
    }
95
96
    @property @safe const pure nothrow
97
    bool isNull() {
98
        return _isNull;
99
    }
100
101
    @safe pure nothrow
102
    void opAssign(T value) {
103
        _value = value;
104
        _isNull = false;
105
    }
106
107
    @safe pure
108
    void opAssign(Nullable!T value) {
109
        if (!value.isNull) {
110
            _value = value;
111
            _isNull = false;
112
        }
113
    }
114
115
    @safe pure nothrow nullify() {
116
        _value = T.init;
117
        _isNull = true;
118
    }
119
120
    @property @safe pure nothrow
121
    inout(T) get() inout {
122
        enum message = "Called `get' on null Option!" ~ T.stringof ~ ".";
123
        assert(!_isNull, message);
124
        return _value;
125
    }
126
127
    alias get this;
128
}
129
130
// Test that Option works for classes.
131
unittest {
132
    class MyClass { }
133
134
    Option!MyClass test = null;
135
    assert(test.isNull);
136
    assertThrown!Throwable(test.get);
137
}
138
139
unittest {
140
    class MyClass { }
141
142
    Option!MyClass test = new MyClass();
143
    test = null;
144
145
    assert(test.isNull);
146
    assertThrown!Throwable(test.get);
147
}
148
149
unittest {
150
    class MyClass { }
151
152
    Option!MyClass test = new MyClass();
153
    assert(!test.isNull);
154
    assertNotThrown!Throwable(test.get);
155
}
156
157
unittest {
158
    class MyClass { }
159
160
    Option!MyClass test;
161
    test = new MyClass();
162
    assert(!test.isNull);
163
    assertNotThrown!Throwable(test.get);
164
}
165
166
// Test that option works for primitives.
167
unittest {
168
    Option!int test;
169
    assert(test.isNull);
170
    assertThrown!Throwable(test.get);
171
}
172
173
unittest {
174
    Option!int test = 3;
175
    test.nullify();
176
    assert(test.isNull);
177
    assertThrown!Throwable(test.get);
178
}
179
180
unittest {
181
    Option!int test = 4;
182
    assert(!test.isNull);
183
    assertNotThrown!Throwable(test.get);
184
}
185
186
unittest {
187
    Option!int test;
188
    test = 4;
189
    assert(!test.isNull);
190
    assertNotThrown!Throwable(test.get);
191
}
192
193
// Test that option supports Nullable for classes.
194
unittest {
195
    class MyClass { }
196
197
    Nullable!MyClass nullableInstance;
198
    Option!MyClass optInstance = nullableInstance;
199
200
    assert(optInstance.isNull);
201
    assertThrown!Throwable(optInstance.get);
202
}
203
204
unittest {
205
    class MyClass { }
206
207
    MyClass instance = new MyClass();
208
209
    Nullable!MyClass nullableInstance = instance;
210
    Option!MyClass optInstance = nullableInstance;
211
212
    assert(!optInstance.isNull);
213
    assertNotThrown!Throwable(optInstance.get);
214
    assert(optInstance == instance);
215
}
216
217
// Test that option supports Nullable for primitives.
218
unittest {
219
    Nullable!int nullableInt;
220
    Option!int optInt = nullableInt;
221
222
    assert(optInt.isNull);
223
    assertThrown!Throwable(optInt.get);
224
}
225
226
unittest {
227
    Nullable!int nullableInt = 3;
228
    Option!int optInt = nullableInt;
229
230
    assert(!optInt.isNull);
231
    assertNotThrown!Throwable(optInt.get);
232
    assert(optInt == 3);
233
}