1 module jcli.core.result;
2 
3 struct ResultOf(alias T)
4 {
5     enum IsVoid = is(T == void);
6     alias This = typeof(this);
7 
8     private
9     {
10         string _error = "I've not been initialised.";
11         static if(!IsVoid)
12             T _value;
13     }
14 
15     static if(IsVoid)
16     {
17         static This ok()()
18         {
19             This t;
20             t._error = null;
21             return t;
22         }
23     }
24     else
25     {
26         static This ok()(T value)
27         {
28             This t;
29             t._error = null;
30             t._value = value;
31             return t;
32         }
33     }
34 
35     static This fail()(string error)
36     {
37         This t;
38         t._error = error;
39         return t;
40     }
41 
42     inout:
43 
44     bool isOk()()
45     {
46         return this._error is null;
47     }
48 
49     string error()()
50     {
51         assert(!this.isOk, "Cannot call .error on an ok result. Please use .isOk to check.");
52         return this._error;
53     }
54 
55     static if(!IsVoid)
56     inout(T) value()() inout
57     {
58         assert(this.isOk, "Cannot call .value on a failed result. Please use .isOk to check.");
59         return this._value;
60     }
61 }
62 ///
63 unittest
64 {
65     auto ok     = ResultOf!int.ok(1);
66     auto fail   = ResultOf!int.fail("Bad");
67     auto init   = ResultOf!int.init;
68     auto void_  = Result.ok();
69 
70     assert(ok.isOk);
71     assert(ok.value == 1);
72 
73     assert(!fail.isOk);
74     assert(fail.error == "Bad");
75 
76     assert(!init.isOk);
77     assert(init.error);
78 
79     assert(void_.isOk);
80 }
81 
82 alias Result = ResultOf!void;
83 
84 auto ok(T)(T value)
85 {
86     return ResultOf!T.ok(value);
87 }
88 
89 auto ok()()
90 {
91     return Result.ok();
92 }
93 
94 auto fail(T)(string error)
95 {
96     return ResultOf!T.fail(error);
97 }