1 /++ Result type.
2  +/
3 module nxt.result;
4 
5 @safe:
6 
7 /++ Result of `T`.
8 	Designed for error handling where an operation can either succeed or fail.
9 	- TODO: Add member `toRange` alias with `opSlice`
10 	- TODO: Add member visit()
11  +/
12 struct Result(T) {
13 	static if (!__traits(isPOD, T))
14 		import core.lifetime : move, moveEmplace;
15 	this(T value) {
16 		static if (__traits(isPOD, T))
17 			_value = value;
18 		else
19 			() @trusted { moveEmplace(value, _value); }(); /+ TODO: remove when compiler does this +/
20 		_isValid = true;
21 	}
22 	ref typeof(this) opAssign(T value) {
23 		static if (__traits(isPOD, T))
24 			_value = value;
25 		else
26 			() @trusted { move(value, _value); }(); /+ TODO: remove when compiler does this +/
27 		_isValid = true;
28 		return this;
29 	}
30 @property:
31 	ref inout(T) value() inout scope return in(isValid) => _value;
32 	// ditto
33 	ref inout(T) opUnary(string op)() inout scope return if (op == "*") => value;
34 	string toString() inout scope pure {
35 		import std.conv : to;
36 		return isValid ? _value.to!string : "invalid";
37 	}
38 pure nothrow @nogc:
39 	bool isValid() const scope => _isValid;
40 	alias hasValue = isValid;
41 	bool opCast(T : bool)() const scope => _isValid;
42 	static typeof(this) invalid() => typeof(this).init;
43 private
44 	T _value;
45 	bool _isValid;
46 }
47 
48 /// to string conversion
49 @safe pure unittest {
50 	alias R = Result!int;
51 	const R r1;
52 	assert(r1.toString == "invalid");
53 	const R r2 = 42;
54 	assert(r2.toString == "42");
55 }
56 
57 /// result of uncopyable type
58 @safe pure nothrow @nogc unittest {
59 	alias T = Uncopyable;
60 	alias R = Result!T;
61 	R r1;
62 	assert(!r1);
63 	assert(r1 == R.invalid);
64 	assert(r1 != R(T.init));
65 	assert(!r1.isValid);
66 	T t = T(42);
67 	r1 = move(t);
68 	assert(r1 != R(T.init));
69 	assert(*r1 == T(42));
70 	R r2 = T(43);
71 	assert(*r2 == T(43));
72 	assert(r2.value == T(43));
73 }
74 
75 version (unittest) {
76 	import core.lifetime : move;
77 	private static struct Uncopyable { this(this) @disable; int _x; }
78 }