Replace Option with Nullable
This commit is contained in:
parent
0fcc83d00e
commit
92284c8541
@ -21,11 +21,11 @@
|
|||||||
module tanya.algorithm.iteration;
|
module tanya.algorithm.iteration;
|
||||||
|
|
||||||
import std.algorithm.comparison;
|
import std.algorithm.comparison;
|
||||||
|
import std.typecons;
|
||||||
import tanya.memory.lifetime;
|
import tanya.memory.lifetime;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
import tanya.meta.transform;
|
import tanya.meta.transform;
|
||||||
import tanya.range;
|
import tanya.range;
|
||||||
import tanya.typecons;
|
|
||||||
|
|
||||||
// These predicates are used to help preserve `const` and `inout` for
|
// These predicates are used to help preserve `const` and `inout` for
|
||||||
// ranges built on other ranges.
|
// ranges built on other ranges.
|
||||||
@ -570,7 +570,7 @@ if (isBidirectionalRange!Range)
|
|||||||
|
|
||||||
private struct SingletonByValue(E)
|
private struct SingletonByValue(E)
|
||||||
{
|
{
|
||||||
private Option!E element;
|
private Nullable!E element;
|
||||||
|
|
||||||
@disable this();
|
@disable this();
|
||||||
|
|
||||||
@ -581,9 +581,9 @@ private struct SingletonByValue(E)
|
|||||||
}
|
}
|
||||||
|
|
||||||
private this(U)(ref U element)
|
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;
|
this.element = element.get;
|
||||||
}
|
}
|
||||||
@ -600,19 +600,19 @@ private struct SingletonByValue(E)
|
|||||||
void popFront()
|
void popFront()
|
||||||
in (!empty)
|
in (!empty)
|
||||||
{
|
{
|
||||||
this.element.reset();
|
this.element.nullify();
|
||||||
}
|
}
|
||||||
|
|
||||||
alias popBack = popFront;
|
alias popBack = popFront;
|
||||||
|
|
||||||
@property bool empty() const
|
@property bool empty() const
|
||||||
{
|
{
|
||||||
return this.element.isNothing;
|
return this.element.isNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property size_t length() const
|
@property size_t length() const
|
||||||
{
|
{
|
||||||
return !this.element.isNothing;
|
return !this.element.isNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto save()
|
auto save()
|
||||||
@ -620,11 +620,6 @@ private struct SingletonByValue(E)
|
|||||||
return SingletonByValue!E(this.element);
|
return SingletonByValue!E(this.element);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto save() const
|
|
||||||
{
|
|
||||||
return SingletonByValue!(const E)(this.element);
|
|
||||||
}
|
|
||||||
|
|
||||||
ref inout(E) opIndex(size_t i) inout
|
ref inout(E) opIndex(size_t i) inout
|
||||||
in (!empty)
|
in (!empty)
|
||||||
in (i == 0)
|
in (i == 0)
|
||||||
@ -675,11 +670,6 @@ private struct SingletonByRef(E)
|
|||||||
return typeof(this)(*this.element);
|
return typeof(this)(*this.element);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto save() const return
|
|
||||||
{
|
|
||||||
return SingletonByRef!(const E)(*this.element);
|
|
||||||
}
|
|
||||||
|
|
||||||
ref inout(E) opIndex(size_t i) inout return
|
ref inout(E) opIndex(size_t i) inout return
|
||||||
in (!empty)
|
in (!empty)
|
||||||
in (i == 0)
|
in (i == 0)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.math.random;
|
module tanya.math.random;
|
||||||
|
|
||||||
|
import std.typecons;
|
||||||
import tanya.memory.allocator;
|
import tanya.memory.allocator;
|
||||||
import tanya.typecons;
|
import tanya.typecons;
|
||||||
|
|
||||||
@ -90,8 +91,8 @@ abstract class EntropySource
|
|||||||
* Postcondition: Returned length is less than or equal to
|
* Postcondition: Returned length is less than or equal to
|
||||||
* $(D_PARAM output) length.
|
* $(D_PARAM output) length.
|
||||||
*/
|
*/
|
||||||
Option!ubyte poll(out ubyte[maxGather] output) @nogc
|
Nullable!ubyte poll(out ubyte[maxGather] output) @nogc
|
||||||
out (length; length.isNothing || length.get <= maxGather);
|
out (length; length.isNull || length.get <= maxGather);
|
||||||
}
|
}
|
||||||
|
|
||||||
version (CRuntime_Bionic)
|
version (CRuntime_Bionic)
|
||||||
@ -151,12 +152,12 @@ version (linux)
|
|||||||
* Returns: Number of bytes that were copied to the $(D_PARAM output)
|
* Returns: Number of bytes that were copied to the $(D_PARAM output)
|
||||||
* or nothing on error.
|
* 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);
|
// int getrandom(void *buf, size_t buflen, unsigned int flags);
|
||||||
import mir.linux._asm.unistd : NR_getrandom;
|
import mir.linux._asm.unistd : NR_getrandom;
|
||||||
auto length = syscall(NR_getrandom, output.ptr, output.length, 0);
|
auto length = syscall(NR_getrandom, output.ptr, output.length, 0);
|
||||||
Option!ubyte ret;
|
Nullable!ubyte ret;
|
||||||
|
|
||||||
if (length >= 0)
|
if (length >= 0)
|
||||||
{
|
{
|
||||||
@ -202,11 +203,11 @@ else version (SecureARC4Random)
|
|||||||
* Returns: Number of bytes that were copied to the $(D_PARAM output)
|
* Returns: Number of bytes that were copied to the $(D_PARAM output)
|
||||||
* or nothing on error.
|
* or nothing on error.
|
||||||
*/
|
*/
|
||||||
override Option!ubyte poll(out ubyte[maxGather] output)
|
override Nullable!ubyte poll(out ubyte[maxGather] output)
|
||||||
@nogc nothrow @safe
|
@nogc nothrow @safe
|
||||||
{
|
{
|
||||||
(() @trusted => arc4random_buf(output.ptr, output.length))();
|
(() @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)
|
* Returns: Number of bytes that were copied to the $(D_PARAM output)
|
||||||
* or nothing on error.
|
* or nothing on error.
|
||||||
*/
|
*/
|
||||||
override Option!ubyte poll(out ubyte[maxGather] output)
|
override Nullable!ubyte poll(out ubyte[maxGather] output)
|
||||||
@nogc nothrow @safe
|
@nogc nothrow @safe
|
||||||
{
|
{
|
||||||
Option!ubyte ret;
|
Nullable!ubyte ret;
|
||||||
|
|
||||||
assert(hProvider > 0, "hProvider not properly initialized");
|
assert(hProvider > 0, "hProvider not properly initialized");
|
||||||
if ((() @trusted => CryptGenRandom(hProvider, output.length, cast(PBYTE) output.ptr))())
|
if ((() @trusted => CryptGenRandom(hProvider, output.length, cast(PBYTE) output.ptr))())
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
module tanya.net.ip;
|
module tanya.net.ip;
|
||||||
|
|
||||||
import std.algorithm.comparison;
|
import std.algorithm.comparison;
|
||||||
|
import std.typecons;
|
||||||
import tanya.algorithm.iteration;
|
import tanya.algorithm.iteration;
|
||||||
import tanya.algorithm.mutation;
|
import tanya.algorithm.mutation;
|
||||||
import tanya.container.string;
|
import tanya.container.string;
|
||||||
@ -242,7 +243,7 @@ struct Address4
|
|||||||
*
|
*
|
||||||
* Returns: $(D_PARAM output).
|
* 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)[]))
|
if (isOutputRange!(OR, const(char)[]))
|
||||||
{
|
{
|
||||||
const octets = (() @trusted => (cast(ubyte*) &this.address)[0 .. 4])();
|
const octets = (() @trusted => (cast(ubyte*) &this.address)[0 .. 4])();
|
||||||
@ -324,10 +325,10 @@ struct Address4
|
|||||||
* R = Input range type.
|
* R = Input range type.
|
||||||
* range = Stringish range containing the address.
|
* 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.
|
* 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)
|
if (isForwardRange!R && is(Unqual!(ElementType!R) == char) && hasLength!R)
|
||||||
{
|
{
|
||||||
Address4 result;
|
Address4 result;
|
||||||
@ -370,10 +371,10 @@ if (isForwardRange!R && is(Unqual!(ElementType!R) == char) && hasLength!R)
|
|||||||
* R = Input range type.
|
* R = Input range type.
|
||||||
* range = $(D_KEYWORD ubyte) range containing the address.
|
* 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.
|
* 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))
|
if (isInputRange!R && is(Unqual!(ElementType!R) == ubyte))
|
||||||
{
|
{
|
||||||
Address4 result;
|
Address4 result;
|
||||||
@ -407,11 +408,11 @@ if (isInputRange!R && is(Unqual!(ElementType!R) == ubyte))
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
ubyte[3] actual = [127, 0, 0];
|
ubyte[3] actual = [127, 0, 0];
|
||||||
assert(address4(actual[]).isNothing);
|
assert(address4(actual[]).isNull);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ubyte[5] actual = [127, 0, 0, 0, 1];
|
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.
|
* R = Input range type.
|
||||||
* range = Stringish range containing the address.
|
* 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.
|
* 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 (isForwardRange!R && is(Unqual!(ElementType!R) == char) && hasLength!R)
|
||||||
{
|
{
|
||||||
if (range.empty)
|
if (range.empty)
|
||||||
@ -1006,10 +1007,10 @@ CopyTail:
|
|||||||
* range = $(D_KEYWORD ubyte) range containing the address.
|
* range = $(D_KEYWORD ubyte) range containing the address.
|
||||||
* scopeID = Scope ID.
|
* 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.
|
* 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))
|
if (isInputRange!R && is(Unqual!(ElementType!R) == ubyte))
|
||||||
{
|
{
|
||||||
Address6 result;
|
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,
|
ubyte[16] actual = [ 1, 2, 3, 4, 5, 6, 7, 8,
|
||||||
9, 10, 11, 12, 13, 14, 15, 16 ];
|
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,
|
ubyte[15] actual = [ 1, 2, 3, 4, 5, 6, 7, 8,
|
||||||
9, 10, 11, 12, 13, 14, 15 ];
|
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,
|
ubyte[17] actual = [ 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||||
10, 11, 12, 13, 14, 15, 16, 17 ];
|
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);
|
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.
|
* Type that can hold one of the types listed as its template parameters.
|
||||||
*
|
*
|
||||||
|
@ -9,17 +9,17 @@ import tanya.range;
|
|||||||
// Rejects malformed addresses
|
// Rejects malformed addresses
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
assert(address4("256.0.0.1").isNothing);
|
assert(address4("256.0.0.1").isNull);
|
||||||
assert(address4(".0.0.1").isNothing);
|
assert(address4(".0.0.1").isNull);
|
||||||
assert(address4("0..0.1").isNothing);
|
assert(address4("0..0.1").isNull);
|
||||||
assert(address4("0.0.0.").isNothing);
|
assert(address4("0.0.0.").isNull);
|
||||||
assert(address4("0.0.").isNothing);
|
assert(address4("0.0.").isNull);
|
||||||
assert(address4("").isNothing);
|
assert(address4("").isNull);
|
||||||
}
|
}
|
||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
assert(address4(cast(ubyte[]) []).isNothing);
|
assert(address4(cast(ubyte[]) []).isNull);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assignment and comparison works
|
// Assignment and comparison works
|
||||||
@ -106,12 +106,12 @@ import tanya.range;
|
|||||||
// Rejects malformed addresses
|
// Rejects malformed addresses
|
||||||
@nogc nothrow @safe unittest
|
@nogc nothrow @safe unittest
|
||||||
{
|
{
|
||||||
assert(address6("").isNothing);
|
assert(address6("").isNull);
|
||||||
assert(address6(":").isNothing);
|
assert(address6(":").isNull);
|
||||||
assert(address6(":a").isNothing);
|
assert(address6(":a").isNull);
|
||||||
assert(address6("a:").isNothing);
|
assert(address6("a:").isNull);
|
||||||
assert(address6("1:2:3:4::6:").isNothing);
|
assert(address6("1:2:3:4::6:").isNull);
|
||||||
assert(address6("fe80:2:3:4::6:7:8%").isNothing);
|
assert(address6("fe80:2:3:4::6:7:8%").isNull);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses embedded IPv4 address
|
// Parses embedded IPv4 address
|
||||||
@ -138,9 +138,9 @@ import tanya.range;
|
|||||||
|
|
||||||
@nogc nothrow @safe unittest
|
@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.").isNull);
|
||||||
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").isNull);
|
||||||
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.").isNull);
|
||||||
assert(address6("fe80:0:0:0:0:0:1.2.3.4%1").get.scopeID == 1);
|
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")));
|
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
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
Variant!(int, double) variant;
|
Variant!(int, double) variant;
|
||||||
|
Loading…
Reference in New Issue
Block a user