Replace Option with Nullable
This commit is contained in:
parent
0fcc83d00e
commit
92284c8541
@ -21,11 +21,11 @@
|
||||
module tanya.algorithm.iteration;
|
||||
|
||||
import std.algorithm.comparison;
|
||||
import std.typecons;
|
||||
import tanya.memory.lifetime;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
import tanya.range;
|
||||
import tanya.typecons;
|
||||
|
||||
// These predicates are used to help preserve `const` and `inout` for
|
||||
// ranges built on other ranges.
|
||||
@ -570,7 +570,7 @@ if (isBidirectionalRange!Range)
|
||||
|
||||
private struct SingletonByValue(E)
|
||||
{
|
||||
private Option!E element;
|
||||
private Nullable!E element;
|
||||
|
||||
@disable this();
|
||||
|
||||
@ -581,9 +581,9 @@ private struct SingletonByValue(E)
|
||||
}
|
||||
|
||||
private this(U)(ref U element)
|
||||
if (is(Unqual!U == Option!(Unqual!E)) || is(Unqual!U == Option!(const E)))
|
||||
if (is(Unqual!U == Nullable!(Unqual!E)) || is(Unqual!U == Nullable!(const E)))
|
||||
{
|
||||
if (!element.isNothing)
|
||||
if (!element.isNull)
|
||||
{
|
||||
this.element = element.get;
|
||||
}
|
||||
@ -600,19 +600,19 @@ private struct SingletonByValue(E)
|
||||
void popFront()
|
||||
in (!empty)
|
||||
{
|
||||
this.element.reset();
|
||||
this.element.nullify();
|
||||
}
|
||||
|
||||
alias popBack = popFront;
|
||||
|
||||
@property bool empty() const
|
||||
{
|
||||
return this.element.isNothing;
|
||||
return this.element.isNull;
|
||||
}
|
||||
|
||||
@property size_t length() const
|
||||
{
|
||||
return !this.element.isNothing;
|
||||
return !this.element.isNull;
|
||||
}
|
||||
|
||||
auto save()
|
||||
@ -620,11 +620,6 @@ private struct SingletonByValue(E)
|
||||
return SingletonByValue!E(this.element);
|
||||
}
|
||||
|
||||
auto save() const
|
||||
{
|
||||
return SingletonByValue!(const E)(this.element);
|
||||
}
|
||||
|
||||
ref inout(E) opIndex(size_t i) inout
|
||||
in (!empty)
|
||||
in (i == 0)
|
||||
@ -675,11 +670,6 @@ private struct SingletonByRef(E)
|
||||
return typeof(this)(*this.element);
|
||||
}
|
||||
|
||||
auto save() const return
|
||||
{
|
||||
return SingletonByRef!(const E)(*this.element);
|
||||
}
|
||||
|
||||
ref inout(E) opIndex(size_t i) inout return
|
||||
in (!empty)
|
||||
in (i == 0)
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
module tanya.math.random;
|
||||
|
||||
import std.typecons;
|
||||
import tanya.memory.allocator;
|
||||
import tanya.typecons;
|
||||
|
||||
@ -90,8 +91,8 @@ abstract class EntropySource
|
||||
* Postcondition: Returned length is less than or equal to
|
||||
* $(D_PARAM output) length.
|
||||
*/
|
||||
Option!ubyte poll(out ubyte[maxGather] output) @nogc
|
||||
out (length; length.isNothing || length.get <= maxGather);
|
||||
Nullable!ubyte poll(out ubyte[maxGather] output) @nogc
|
||||
out (length; length.isNull || length.get <= maxGather);
|
||||
}
|
||||
|
||||
version (CRuntime_Bionic)
|
||||
@ -151,12 +152,12 @@ version (linux)
|
||||
* Returns: Number of bytes that were copied to the $(D_PARAM output)
|
||||
* or nothing on error.
|
||||
*/
|
||||
override Option!ubyte poll(out ubyte[maxGather] output) @nogc nothrow
|
||||
override Nullable!ubyte poll(out ubyte[maxGather] output) @nogc nothrow
|
||||
{
|
||||
// int getrandom(void *buf, size_t buflen, unsigned int flags);
|
||||
import mir.linux._asm.unistd : NR_getrandom;
|
||||
auto length = syscall(NR_getrandom, output.ptr, output.length, 0);
|
||||
Option!ubyte ret;
|
||||
Nullable!ubyte ret;
|
||||
|
||||
if (length >= 0)
|
||||
{
|
||||
@ -202,11 +203,11 @@ else version (SecureARC4Random)
|
||||
* Returns: Number of bytes that were copied to the $(D_PARAM output)
|
||||
* or nothing on error.
|
||||
*/
|
||||
override Option!ubyte poll(out ubyte[maxGather] output)
|
||||
override Nullable!ubyte poll(out ubyte[maxGather] output)
|
||||
@nogc nothrow @safe
|
||||
{
|
||||
(() @trusted => arc4random_buf(output.ptr, output.length))();
|
||||
return Option!ubyte(cast(ubyte) (output.length));
|
||||
return Nullable!ubyte(cast(ubyte) (output.length));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -310,10 +311,10 @@ else version (Windows)
|
||||
* Returns: Number of bytes that were copied to the $(D_PARAM output)
|
||||
* or nothing on error.
|
||||
*/
|
||||
override Option!ubyte poll(out ubyte[maxGather] output)
|
||||
override Nullable!ubyte poll(out ubyte[maxGather] output)
|
||||
@nogc nothrow @safe
|
||||
{
|
||||
Option!ubyte ret;
|
||||
Nullable!ubyte ret;
|
||||
|
||||
assert(hProvider > 0, "hProvider not properly initialized");
|
||||
if ((() @trusted => CryptGenRandom(hProvider, output.length, cast(PBYTE) output.ptr))())
|
||||
|
@ -15,6 +15,7 @@
|
||||
module tanya.net.ip;
|
||||
|
||||
import std.algorithm.comparison;
|
||||
import std.typecons;
|
||||
import tanya.algorithm.iteration;
|
||||
import tanya.algorithm.mutation;
|
||||
import tanya.container.string;
|
||||
@ -242,7 +243,7 @@ struct Address4
|
||||
*
|
||||
* Returns: $(D_PARAM output).
|
||||
*/
|
||||
OR toString(OR)(OR output) const @nogc nothrow pure @safe
|
||||
OR toString(OR)(OR output) const
|
||||
if (isOutputRange!(OR, const(char)[]))
|
||||
{
|
||||
const octets = (() @trusted => (cast(ubyte*) &this.address)[0 .. 4])();
|
||||
@ -324,10 +325,10 @@ struct Address4
|
||||
* R = Input range type.
|
||||
* range = Stringish range containing the address.
|
||||
*
|
||||
* Returns: $(D_PSYMBOL Option) containing the address if the parsing was
|
||||
* Returns: $(D_PSYMBOL Nullable) containing the address if the parsing was
|
||||
* successful, or nothing otherwise.
|
||||
*/
|
||||
Option!Address4 address4(R)(R range)
|
||||
Nullable!Address4 address4(R)(R range)
|
||||
if (isForwardRange!R && is(Unqual!(ElementType!R) == char) && hasLength!R)
|
||||
{
|
||||
Address4 result;
|
||||
@ -370,10 +371,10 @@ if (isForwardRange!R && is(Unqual!(ElementType!R) == char) && hasLength!R)
|
||||
* R = Input range type.
|
||||
* range = $(D_KEYWORD ubyte) range containing the address.
|
||||
*
|
||||
* Returns: $(D_PSYMBOL Option) containing the address if the $(D_PARAM range)
|
||||
* Returns: $(D_PSYMBOL Nullable) containing the address if the $(D_PARAM range)
|
||||
* contains exactly 4 bytes, or nothing otherwise.
|
||||
*/
|
||||
Option!Address4 address4(R)(R range)
|
||||
Nullable!Address4 address4(R)(R range)
|
||||
if (isInputRange!R && is(Unqual!(ElementType!R) == ubyte))
|
||||
{
|
||||
Address4 result;
|
||||
@ -407,11 +408,11 @@ if (isInputRange!R && is(Unqual!(ElementType!R) == ubyte))
|
||||
}
|
||||
{
|
||||
ubyte[3] actual = [127, 0, 0];
|
||||
assert(address4(actual[]).isNothing);
|
||||
assert(address4(actual[]).isNull);
|
||||
}
|
||||
{
|
||||
ubyte[5] actual = [127, 0, 0, 0, 1];
|
||||
assert(address4(actual[]).isNothing);
|
||||
assert(address4(actual[]).isNull);
|
||||
}
|
||||
}
|
||||
|
||||
@ -795,10 +796,10 @@ in (digit < 16)
|
||||
* R = Input range type.
|
||||
* range = Stringish range containing the address.
|
||||
*
|
||||
* Returns: $(D_PSYMBOL Option) containing the address if the parsing was
|
||||
* Returns: $(D_PSYMBOL Nullable) containing the address if the parsing was
|
||||
* successful, or nothing otherwise.
|
||||
*/
|
||||
Option!Address6 address6(R)(R range)
|
||||
Nullable!Address6 address6(R)(R range)
|
||||
if (isForwardRange!R && is(Unqual!(ElementType!R) == char) && hasLength!R)
|
||||
{
|
||||
if (range.empty)
|
||||
@ -1006,10 +1007,10 @@ CopyTail:
|
||||
* range = $(D_KEYWORD ubyte) range containing the address.
|
||||
* scopeID = Scope ID.
|
||||
*
|
||||
* Returns: $(D_PSYMBOL Option) containing the address if the $(D_PARAM range)
|
||||
* Returns: $(D_PSYMBOL Nullable) containing the address if the $(D_PARAM range)
|
||||
* contains exactly 16 bytes, or nothing otherwise.
|
||||
*/
|
||||
Option!Address6 address6(R)(R range, uint scopeID = 0)
|
||||
Nullable!Address6 address6(R)(R range, uint scopeID = 0)
|
||||
if (isInputRange!R && is(Unqual!(ElementType!R) == ubyte))
|
||||
{
|
||||
Address6 result;
|
||||
@ -1030,20 +1031,20 @@ if (isInputRange!R && is(Unqual!(ElementType!R) == ubyte))
|
||||
{
|
||||
ubyte[16] actual = [ 1, 2, 3, 4, 5, 6, 7, 8,
|
||||
9, 10, 11, 12, 13, 14, 15, 16 ];
|
||||
assert(!address6(actual[]).isNothing);
|
||||
assert(!address6(actual[]).isNull);
|
||||
}
|
||||
{
|
||||
ubyte[15] actual = [ 1, 2, 3, 4, 5, 6, 7, 8,
|
||||
9, 10, 11, 12, 13, 14, 15 ];
|
||||
assert(address6(actual[]).isNothing);
|
||||
assert(address6(actual[]).isNull);
|
||||
}
|
||||
{
|
||||
ubyte[17] actual = [ 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15, 16, 17 ];
|
||||
assert(address6(actual[]).isNothing);
|
||||
assert(address6(actual[]).isNull);
|
||||
}
|
||||
{
|
||||
assert(address6(cast(ubyte[]) []).isNothing);
|
||||
assert(address6(cast(ubyte[]) []).isNull);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,274 +153,6 @@ template tuple(Names...)
|
||||
assert(t.two == 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* $(D_PSYMBOL Option) is a type that contains an optional value.
|
||||
*
|
||||
* Params:
|
||||
* T = Type of the encapsulated value.
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL option).
|
||||
*/
|
||||
struct Option(T)
|
||||
{
|
||||
private bool isNothing_ = true;
|
||||
private T value = void;
|
||||
|
||||
/**
|
||||
* Constructs a new option with $(D_PARAM value).
|
||||
*
|
||||
* Params:
|
||||
* value = Encapsulated value.
|
||||
*/
|
||||
this()(ref T value)
|
||||
{
|
||||
this.value = value;
|
||||
this.isNothing_ = false;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
this()(T value) @trusted
|
||||
{
|
||||
moveEmplace(value, this.value);
|
||||
this.isNothing_ = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the option is just a value or nothing.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if this $(D_PSYMBOL Option) contains a nothing,
|
||||
* $(D_KEYWORD false) if it contains a value.
|
||||
*/
|
||||
@property bool isNothing() const
|
||||
{
|
||||
return this.isNothing_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encapsulated value.
|
||||
*
|
||||
* Returns: Value encapsulated in this $(D_PSYMBOL Option).
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL or).
|
||||
*
|
||||
* Precondition: `!isNothing`.
|
||||
*/
|
||||
@property ref inout(T) get() inout
|
||||
in (!isNothing, "Option is nothing")
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encapsulated value if available or a default value
|
||||
* otherwise.
|
||||
*
|
||||
* Note that the contained value can be returned by reference only if the
|
||||
* default value is passed by reference as well.
|
||||
*
|
||||
* Params:
|
||||
* U = Type of the default value.
|
||||
* defaultValue = Default value.
|
||||
*
|
||||
* Returns: The value of this $(D_PSYMBOL Option) if available,
|
||||
* $(D_PARAM defaultValue) otherwise.
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL isNothing), $(D_PSYMBOL get).
|
||||
*/
|
||||
@property U or(U)(U defaultValue) inout
|
||||
if (is(U == T) && isCopyable!T)
|
||||
{
|
||||
return isNothing ? defaultValue : this.value;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
@property ref inout(T) or(ref inout(T) defaultValue) inout
|
||||
{
|
||||
return isNothing ? defaultValue : this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts this $(D_PSYMBOL Option) to $(D_KEYWORD bool).
|
||||
*
|
||||
* An $(D_PSYMBOL Option) is $(D_KEYWORD true) if it contains a value,
|
||||
* ($D_KEYWORD false) if it contains nothing.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if this $(D_PSYMBOL Option) contains a value,
|
||||
* ($D_KEYWORD false) if it contains nothing.
|
||||
*/
|
||||
bool opCast(U : bool)()
|
||||
{
|
||||
return !isNothing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this $(D_PSYMBOL Option) with $(D_PARAM that).
|
||||
*
|
||||
* If both objects are options of the same type and they don't contain a
|
||||
* value, they are considered equal. If only one of them contains a value,
|
||||
* they aren't equal. Otherwise, the encapsulated values are compared for
|
||||
* equality.
|
||||
*
|
||||
* If $(D_PARAM U) is a type comparable with the type encapsulated by this
|
||||
* $(D_PSYMBOL Option), the value of this $(D_PSYMBOL Option) is compared
|
||||
* with $(D_PARAM that), this $(D_PSYMBOL Option) must have a value then.
|
||||
*
|
||||
* Params:
|
||||
* U = Type of the object to compare with.
|
||||
* that = Object to compare with.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if this $(D_PSYMBOL Option) and
|
||||
* $(D_PARAM that) are equal, $(D_KEYWORD false) if not.
|
||||
*
|
||||
* Precondition: `!isNothing` if $(D_PARAM U) is equality comparable with
|
||||
* $(D_PARAM T).
|
||||
*/
|
||||
bool opEquals(U)(auto ref const U that) const
|
||||
if (is(U == Option))
|
||||
{
|
||||
if (!isNothing && !that.isNothing)
|
||||
{
|
||||
return this.value == that.value;
|
||||
}
|
||||
return isNothing == that.isNothing;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
bool opEquals(U)(auto ref const U that) const
|
||||
if (ifTestable!(U, a => a == T.init) && !is(U == Option))
|
||||
in (!isNothing)
|
||||
{
|
||||
return get == that;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets this $(D_PSYMBOL Option) and destroys the contained value.
|
||||
*
|
||||
* $(D_PSYMBOL reset) can be safely called on an $(D_PSYMBOL Option) that
|
||||
* doesn't contain any value.
|
||||
*/
|
||||
void reset()
|
||||
{
|
||||
static if (hasElaborateDestructor!T)
|
||||
{
|
||||
destroy(this.value);
|
||||
}
|
||||
this.isNothing_ = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a new value.
|
||||
*
|
||||
* Params:
|
||||
* U = Type of the new value.
|
||||
* that = New value.
|
||||
*
|
||||
* Returns: $(D_KEYWORD this).
|
||||
*/
|
||||
ref typeof(this) opAssign(U)(ref U that)
|
||||
if (is(U : T) && !is(U == Option))
|
||||
{
|
||||
this.value = that;
|
||||
this.isNothing_ = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
ref typeof(this) opAssign(U)(U that)
|
||||
if (is(U == T))
|
||||
{
|
||||
move(that, this.value);
|
||||
this.isNothing_ = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
ref typeof(this) opAssign(U)(ref U that)
|
||||
if (is(U == Option))
|
||||
{
|
||||
if (that.isNothing)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.value = that.get;
|
||||
this.isNothing_ = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
ref typeof(this) opAssign(U)(U that)
|
||||
if (is(U == Option))
|
||||
{
|
||||
move(that.value, this.value);
|
||||
this.isNothing_ = that.isNothing_;
|
||||
return this;
|
||||
}
|
||||
|
||||
version (D_Ddoc)
|
||||
{
|
||||
/**
|
||||
* If $(D_PARAM T) has a `toHash()` method, $(D_PSYMBOL Option) defines
|
||||
* `toHash()` which returns `T.toHash()` if it is set or 0 otherwise.
|
||||
*
|
||||
* Returns: Hash value.
|
||||
*/
|
||||
size_t toHash() const;
|
||||
}
|
||||
else static if (is(typeof(T.init.toHash()) == size_t))
|
||||
{
|
||||
size_t toHash() const
|
||||
{
|
||||
return isNothing ? 0U : this.value.toHash();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
Option!int option;
|
||||
assert(option.isNothing);
|
||||
assert(option.or(8) == 8);
|
||||
|
||||
option = 5;
|
||||
assert(!option.isNothing);
|
||||
assert(option.get == 5);
|
||||
assert(option.or(8) == 5);
|
||||
|
||||
option.reset();
|
||||
assert(option.isNothing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new $(D_PSYMBOL Option).
|
||||
*
|
||||
* Params:
|
||||
* T = Option type.
|
||||
* value = Initial value.
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL Option).
|
||||
*/
|
||||
Option!T option(T)(auto ref T value)
|
||||
{
|
||||
return Option!T(forward!value);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
Option!T option(T)()
|
||||
{
|
||||
return Option!T();
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
assert(option!int().isNothing);
|
||||
assert(option(5) == 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Type that can hold one of the types listed as its template parameters.
|
||||
*
|
||||
|
@ -9,17 +9,17 @@ import tanya.range;
|
||||
// Rejects malformed addresses
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
assert(address4("256.0.0.1").isNothing);
|
||||
assert(address4(".0.0.1").isNothing);
|
||||
assert(address4("0..0.1").isNothing);
|
||||
assert(address4("0.0.0.").isNothing);
|
||||
assert(address4("0.0.").isNothing);
|
||||
assert(address4("").isNothing);
|
||||
assert(address4("256.0.0.1").isNull);
|
||||
assert(address4(".0.0.1").isNull);
|
||||
assert(address4("0..0.1").isNull);
|
||||
assert(address4("0.0.0.").isNull);
|
||||
assert(address4("0.0.").isNull);
|
||||
assert(address4("").isNull);
|
||||
}
|
||||
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
assert(address4(cast(ubyte[]) []).isNothing);
|
||||
assert(address4(cast(ubyte[]) []).isNull);
|
||||
}
|
||||
|
||||
// Assignment and comparison works
|
||||
@ -106,12 +106,12 @@ import tanya.range;
|
||||
// Rejects malformed addresses
|
||||
@nogc nothrow @safe unittest
|
||||
{
|
||||
assert(address6("").isNothing);
|
||||
assert(address6(":").isNothing);
|
||||
assert(address6(":a").isNothing);
|
||||
assert(address6("a:").isNothing);
|
||||
assert(address6("1:2:3:4::6:").isNothing);
|
||||
assert(address6("fe80:2:3:4::6:7:8%").isNothing);
|
||||
assert(address6("").isNull);
|
||||
assert(address6(":").isNull);
|
||||
assert(address6(":a").isNull);
|
||||
assert(address6("a:").isNull);
|
||||
assert(address6("1:2:3:4::6:").isNull);
|
||||
assert(address6("fe80:2:3:4::6:7:8%").isNull);
|
||||
}
|
||||
|
||||
// Parses embedded IPv4 address
|
||||
@ -138,9 +138,9 @@ import tanya.range;
|
||||
|
||||
@nogc nothrow @safe unittest
|
||||
{
|
||||
assert(address6("0:0:0:0:0:0:1.2.3.").isNothing);
|
||||
assert(address6("0:0:0:0:0:0:1.2:3.4").isNothing);
|
||||
assert(address6("0:0:0:0:0:0:1.2.3.4.").isNothing);
|
||||
assert(address6("0:0:0:0:0:0:1.2.3.").isNull);
|
||||
assert(address6("0:0:0:0:0:0:1.2:3.4").isNull);
|
||||
assert(address6("0:0:0:0:0:0:1.2.3.4.").isNull);
|
||||
assert(address6("fe80:0:0:0:0:0:1.2.3.4%1").get.scopeID == 1);
|
||||
}
|
||||
|
||||
|
@ -22,120 +22,6 @@ import tanya.typecons;
|
||||
static assert(!is(Tuple!(int, "first", double, "second", char, "third")));
|
||||
}
|
||||
|
||||
// Assigns a new value
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
Option!int option = 5;
|
||||
option = 8;
|
||||
assert(!option.isNothing);
|
||||
assert(option == 8);
|
||||
}
|
||||
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
Option!int option;
|
||||
const int newValue = 8;
|
||||
assert(option.isNothing);
|
||||
option = newValue;
|
||||
assert(!option.isNothing);
|
||||
assert(option == newValue);
|
||||
}
|
||||
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
Option!int option1;
|
||||
Option!int option2 = 5;
|
||||
assert(option1.isNothing);
|
||||
option1 = option2;
|
||||
assert(!option1.isNothing);
|
||||
assert(option1.get == 5);
|
||||
}
|
||||
|
||||
// Constructs with a value passed by reference
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
int i = 5;
|
||||
assert(Option!int(i).get == 5);
|
||||
}
|
||||
|
||||
// Moving
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
static assert(is(typeof(Option!NonCopyable(NonCopyable()))));
|
||||
// The value cannot be returned by reference because the default value
|
||||
// isn't passed by reference
|
||||
static assert(!is(typeof(Option!DisabledPostblit().or(NonCopyable()))));
|
||||
}
|
||||
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
NonCopyable notCopyable;
|
||||
static assert(is(typeof(Option!NonCopyable().or(notCopyable))));
|
||||
}
|
||||
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
Option!NonCopyable option;
|
||||
assert(option.isNothing);
|
||||
option = NonCopyable();
|
||||
assert(!option.isNothing);
|
||||
}
|
||||
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
Option!NonCopyable option;
|
||||
assert(option.isNothing);
|
||||
option = Option!NonCopyable(NonCopyable());
|
||||
assert(!option.isNothing);
|
||||
}
|
||||
|
||||
// Cast to bool is done before touching the encapsulated value
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
assert(Option!bool(false));
|
||||
}
|
||||
|
||||
// Option can be const
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
assert((const Option!int(5)).get == 5);
|
||||
assert((const Option!int()).or(5) == 5);
|
||||
}
|
||||
|
||||
// Equality
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
assert(Option!int() == Option!int());
|
||||
assert(Option!int(0) != Option!int());
|
||||
assert(Option!int(5) == Option!int(5));
|
||||
assert(Option!int(5) == 5);
|
||||
assert(Option!int(5) == cast(ubyte) 5);
|
||||
}
|
||||
|
||||
// Returns default value
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
int i = 5;
|
||||
assert(((ref e) => e)(Option!int().or(i)) == 5);
|
||||
}
|
||||
|
||||
// Implements toHash() for nothing
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
alias OptionT = Option!Hashable;
|
||||
assert(OptionT().toHash() == 0U);
|
||||
assert(OptionT(Hashable(1U)).toHash() == 1U);
|
||||
}
|
||||
|
||||
// Can assign Option that is nothing
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
auto option1 = Option!int(5);
|
||||
Option!int option2;
|
||||
option1 = option2;
|
||||
assert(option1.isNothing);
|
||||
}
|
||||
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
Variant!(int, double) variant;
|
||||
|
Loading…
Reference in New Issue
Block a user