summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--source/tanya/algorithm/iteration.d2
-rw-r--r--source/tanya/net/ip.d102
-rw-r--r--source/tanya/typecons.d273
-rw-r--r--tests/tanya/tests/typecons.d101
5 files changed, 49 insertions, 431 deletions
diff --git a/README.md b/README.md
index 053fce9..d6b1074 100644
--- a/README.md
+++ b/README.md
@@ -163,7 +163,7 @@ parameter is used)
| DMD | GCC |
|:-------:|:---------:|
-| 2.098.1 | 11.2 |
+| 2.100.0 | 12.1 |
## Further characteristics
diff --git a/source/tanya/algorithm/iteration.d b/source/tanya/algorithm/iteration.d
index 8074fc1..f2019da 100644
--- a/source/tanya/algorithm/iteration.d
+++ b/source/tanya/algorithm/iteration.d
@@ -226,7 +226,7 @@ if (F.length == 1)
*
* Returns: Accumulated value.
*/
- auto foldr(R, T)(scope R range, scope return auto ref T init)
+ auto foldr(R, T)(scope R range, auto ref T init)
if (isBidirectionalRange!R)
{
if (range.empty)
diff --git a/source/tanya/net/ip.d b/source/tanya/net/ip.d
index 54a27e3..73e7f84 100644
--- a/source/tanya/net/ip.d
+++ b/source/tanya/net/ip.d
@@ -16,6 +16,7 @@ module tanya.net.ip;
import std.algorithm.comparison;
import std.ascii;
+import std.sumtype;
import std.typecons;
import tanya.algorithm.iteration;
import tanya.algorithm.mutation;
@@ -28,7 +29,6 @@ import tanya.meta.transform;
import tanya.net.iface;
import tanya.net.inet;
import tanya.range;
-import tanya.typecons;
/**
* IPv4 internet address.
@@ -1061,7 +1061,7 @@ if (isInputRange!R && is(Unqual!(ElementType!R) == ubyte))
*/
struct Address
{
- private Variant!(Address4, Address6) address;
+ private SumType!(Address4, Address6) address;
@disable this();
@@ -1095,7 +1095,10 @@ struct Address
*/
bool isV4() const @nogc nothrow pure @safe
{
- return this.address.peek!Address4;
+ return this.address.match!(
+ (Address4 address4) => true,
+ (Address6 address6) => false
+ );
}
///
@@ -1112,7 +1115,10 @@ struct Address
*/
bool isV6() const @nogc nothrow pure @safe
{
- return this.address.peek!Address6;
+ return this.address.match!(
+ (Address4 address4) => false,
+ (Address6 address6) => true
+ );
}
///
@@ -1131,14 +1137,12 @@ struct Address
*
* Precondition: This is an IPv4 address.
*/
- ref inout(Address4) toV4() inout @nogc nothrow pure @safe
- in
+ Address4 toV4() inout @nogc nothrow pure @safe
{
- assert(this.address.peek!Address4);
- }
- do
- {
- return this.address.get!Address4;
+ return this.address.match!(
+ (Address4 address4) => address4,
+ _ => assert(false, "Not an IPv4 address")
+ );
}
///
@@ -1158,14 +1162,12 @@ struct Address
*
* Precondition: This is an IPv6 address.
*/
- ref inout(Address6) toV6() inout @nogc nothrow pure @safe
- in
- {
- assert(this.address.peek!Address6);
- }
- do
+ Address6 toV6() inout @nogc nothrow pure @safe
{
- return this.address.get!Address6;
+ return this.address.match!(
+ (Address6 address6) => address6,
+ _ => assert(false, "Not an IPv6 address")
+ );
}
///
@@ -1185,17 +1187,11 @@ struct Address
* $(D_PSYMBOL Address6.loopback).
*/
bool isLoopback() const @nogc nothrow pure @safe
- in
- {
- assert(this.address.hasValue);
- }
- do
{
- if (this.address.peek!Address4)
- {
- return this.address.get!Address4.isLoopback();
- }
- return this.address.get!Address6.isLoopback();
+ return this.address.match!(
+ (Address4 address) => address.isLoopback(),
+ (Address6 address) => address.isLoopback()
+ );
}
///
@@ -1215,17 +1211,11 @@ struct Address
* $(D_PSYMBOL Address6.isMulticast).
*/
bool isMulticast() const @nogc nothrow pure @safe
- in
- {
- assert(this.address.hasValue);
- }
- do
{
- if (this.address.peek!Address4)
- {
- return this.address.get!Address4.isMulticast();
- }
- return this.address.get!Address6.isMulticast();
+ return this.address.match!(
+ (Address4 address) => address.isMulticast(),
+ (Address6 address) => address.isMulticast()
+ );
}
///
@@ -1244,17 +1234,11 @@ struct Address
* See_Also: $(D_PSYMBOL Address4.isAny), $(D_PSYMBOL Address6.isAny).
*/
bool isAny() const @nogc nothrow pure @safe
- in
{
- assert(this.address.hasValue);
- }
- do
- {
- if (this.address.peek!Address4)
- {
- return this.address.get!Address4.isAny();
- }
- return this.address.get!Address6.isAny();
+ return this.address.match!(
+ (Address4 address) => address.isAny(),
+ (Address6 address) => address.isAny()
+ );
}
///
@@ -1277,14 +1261,22 @@ struct Address
* otherwise.
*/
bool opEquals(T)(T that) const
- if (is(Unqual!T == Address4) || is(Unqual!T == Address6))
+ if (is(Unqual!T == Address4))
{
- alias AddressType = Unqual!T;
- if (this.address.peek!AddressType)
- {
- return this.address.get!AddressType == that;
- }
- return false;
+ return this.address.match!(
+ (Address4 address) => address == that,
+ (Address6 address) => false
+ );
+ }
+
+ ///
+ bool opEquals(T)(T that) const
+ if (is(Unqual!T == Address6))
+ {
+ return this.address.match!(
+ (Address4 address) => false,
+ (Address6 address) => address == that,
+ );
}
///
diff --git a/source/tanya/typecons.d b/source/tanya/typecons.d
index 5e570f6..68c629e 100644
--- a/source/tanya/typecons.d
+++ b/source/tanya/typecons.d
@@ -152,276 +152,3 @@ template tuple(Names...)
assert(t.one == 20);
assert(t.two == 5);
}
-
-/**
- * Type that can hold one of the types listed as its template parameters.
- *
- * $(D_PSYMBOL Variant) is a type similar to $(D_KEYWORD union), but
- * $(D_PSYMBOL Variant) keeps track of the actually used type and throws an
- * assertion error when trying to access an invalid type at runtime.
- *
- * Params:
- * Specs = Types this $(D_SPYBMOL Variant) can hold.
- */
-template Variant(Specs...)
-if (isTypeTuple!Specs && NoDuplicates!Specs.length == Specs.length)
-{
- union AlignedUnion(Args...)
- {
- static if (Args.length > 0)
- {
- Args[0] value;
- }
- static if (Args.length > 1)
- {
- AlignedUnion!(Args[1 .. $]) rest;
- }
- }
-
- private struct VariantAccessorInfo
- {
- string accessor;
- ptrdiff_t tag;
- }
-
- template accessor(T, Union)
- {
- enum VariantAccessorInfo info = accessorImpl!(T, Union, 1);
- enum accessor = VariantAccessorInfo("this.values" ~ info.accessor, info.tag);
- }
-
- template accessorImpl(T, Union, size_t tag)
- {
- static if (is(T == typeof(Union.value)))
- {
- enum accessorImpl = VariantAccessorInfo(".value", tag);
- }
- else
- {
- enum VariantAccessorInfo info = accessorImpl!(T, typeof(Union.rest), tag + 1);
- enum accessorImpl = VariantAccessorInfo(".rest" ~ info.accessor, info.tag);
- }
- }
-
- struct Variant
- {
- /// Types can be present in this $(D_PSYMBOL Variant).
- alias Types = Specs;
-
- private ptrdiff_t tag = -1;
- private AlignedUnion!Types values;
-
- /**
- * Constructs this $(D_PSYMBOL Variant) with one of the types supported
- * in it.
- *
- * Params:
- * T = Type of the initial value.
- * value = Initial value.
- */
- this(T)(ref T value)
- if (canFind!(T, Types))
- {
- copyAssign!T(value);
- }
-
- /// ditto
- this(T)(T value)
- if (canFind!(T, Types))
- {
- moveAssign!T(value);
- }
-
- ~this()
- {
- reset();
- }
-
- this(this)
- {
- alias pred(U) = hasElaborateCopyConstructor!(U.Seq[1]);
- static foreach (Type; Filter!(pred, Enumerate!Types))
- {
- if (this.tag == Type.Seq[0])
- {
- get!(Type.Seq[1]).__postblit();
- }
- }
- }
-
- /**
- * Tells whether this $(D_PSYMBOL Variant) is initialized.
- *
- * Returns: $(D_KEYWORD true) if this $(D_PSYMBOL Variant) contains a
- * value, $(D_KEYWORD false) otherwise.
- */
- bool hasValue() const
- {
- return this.tag != -1;
- }
-
- /**
- * Tells whether this $(D_PSYMBOL Variant) holds currently a value of
- * type $(D_PARAM T).
- *
- * Params:
- * T = Examined type.
- *
- * Returns: $(D_KEYWORD true) if this $(D_PSYMBOL Variant) currently
- * contains a value of type $(D_PARAM T), $(D_KEYWORD false)
- * otherwise.
- */
- bool peek(T)() const
- if (canFind!(T, Types))
- {
- return this.tag == staticIndexOf!(T, Types);
- }
-
- /**
- * Returns the underlying value, assuming it is of the type $(D_PARAM T).
- *
- * Params:
- * T = Type of the value should be returned.
- *
- * Returns: The underyling value.
- *
- * Precondition: The $(D_PSYMBOL Variant) has a value.
- *
- * See_Also: $(D_PSYMBOL peek), $(D_PSYMBOL hasValue).
- */
- ref inout(T) get(T)() inout
- if (canFind!(T, Types))
- in
- {
- assert(this.tag == staticIndexOf!(T, Types), "Variant isn't initialized");
- }
- do
- {
- mixin("return " ~ accessor!(T, AlignedUnion!Types).accessor ~ ";");
- }
-
- /**
- * Reassigns the value.
- *
- * Params:
- * T = Type of the new value
- * that = New value.
- *
- * Returns: $(D_KEYWORD this).
- */
- ref typeof(this) opAssign(T)(T that)
- if (canFind!(T, Types))
- {
- reset();
- return moveAssign!T(that);
- }
-
- /// ditto
- ref typeof(this) opAssign(T)(ref T that)
- if (canFind!(T, Types))
- {
- reset();
- return copyAssign!T(that);
- }
-
- private ref typeof(this) moveAssign(T)(ref T that) @trusted
- {
- this.tag = staticIndexOf!(T, Types);
-
- enum string accessorMixin = accessor!(T, AlignedUnion!Types).accessor;
- moveEmplace(that, mixin(accessorMixin));
-
- return this;
- }
-
- private ref typeof(this) copyAssign(T)(ref T that) return
- {
- this.tag = staticIndexOf!(T, Types);
-
- enum string accessorMixin = accessor!(T, AlignedUnion!Types).accessor;
- emplace!T((() @trusted => (&mixin(accessorMixin))[0 .. 1])(), that);
-
- return this;
- }
-
- private void reset()
- {
- alias pred(U) = hasElaborateDestructor!(U.Seq[1]);
- static foreach (Type; Filter!(pred, Enumerate!Types))
- {
- if (this.tag == Type.Seq[0])
- {
- destroy(get!(Type.Seq[1]));
- }
- }
- }
-
- /**
- * Returns $(D_PSYMBOL TypeInfo) corresponding to the current type.
- *
- * If this $(D_PSYMBOL Variant) isn't initialized, returns
- * $(D_KEYWORD null).
- *
- * Returns: $(D_PSYMBOL TypeInfo) of the current type.
- */
- @property TypeInfo type()
- {
- static foreach (i, Type; Types)
- {
- if (this.tag == i)
- {
- return typeid(Type);
- }
- }
- return null;
- }
-
- /**
- * Compares this $(D_PSYMBOL Variant) with another one with the same
- * specification for equality.
- *
- * $(UL
- * $(LI If both hold values of the same type, these values are
- * compared.)
- * $(LI If they hold values of different types, then the
- * $(D_PSYMBOL Variant)s aren't equal.)
- * $(LI If only one of them is initialized but another one not, they
- * aren't equal.)
- * $(LI If neither of them is initialized, they are equal.)
- * )
- *
- * Params:
- * that = The $(D_PSYMBOL Variant) to compare with.
- *
- * Returns: $(D_KEYWORD true) if this $(D_PSYMBOL Variant) is equal to
- * $(D_PARAM that), $(D_KEYWORD false) otherwise.
- */
- bool opEquals()(auto ref inout(Variant) that) inout
- {
- if (this.tag != that.tag)
- {
- return false;
- }
- static foreach (i, Type; Types)
- {
- if (this.tag == i)
- {
- return get!Type == that.get!Type;
- }
- }
- return true;
- }
- }
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- Variant!(int, double) variant = 5;
- assert(variant.peek!int);
- assert(variant.get!int == 5);
-
- variant = 5.4;
- assert(!variant.peek!int);
- assert(variant.get!double == 5.4);
-}
diff --git a/tests/tanya/tests/typecons.d b/tests/tanya/tests/typecons.d
index 4765f77..152370c 100644
--- a/tests/tanya/tests/typecons.d
+++ b/tests/tanya/tests/typecons.d
@@ -21,104 +21,3 @@ import tanya.typecons;
static assert(!is(Tuple!(int, double, char)));
static assert(!is(Tuple!(int, "first", double, "second", char, "third")));
}
-
-@nogc nothrow pure @safe unittest
-{
- Variant!(int, double) variant;
- variant = 5;
- assert(variant.peek!int);
-}
-
-@nogc nothrow pure @safe unittest
-{
- Variant!(int, double) variant;
- variant = 5.0;
- assert(!variant.peek!int);
-}
-
-@nogc nothrow pure @safe unittest
-{
- Variant!(int, double) variant = 5;
- assert(variant.get!int == 5);
-}
-
-@nogc nothrow pure @safe unittest
-{
- static assert(is(Variant!(int, float)));
- static assert(is(Variant!int));
-}
-
-@nogc nothrow pure @safe unittest
-{
- static struct WithDestructorAndCopy
- {
- this(this) @nogc nothrow pure @safe
- {
- }
-
- ~this() @nogc nothrow pure @safe
- {
- }
- }
- static assert(is(Variant!WithDestructorAndCopy));
-}
-
-// Equality compares the underlying objects
-@nogc nothrow pure @safe unittest
-{
- Variant!(int, double) variant1 = 5;
- Variant!(int, double) variant2 = 5;
- assert(variant1 == variant2);
-}
-
-@nogc nothrow pure @safe unittest
-{
- Variant!(int, double) variant1 = 5;
- Variant!(int, double) variant2 = 6;
- assert(variant1 != variant2);
-}
-
-// Differently typed variants aren't equal
-@nogc nothrow pure @safe unittest
-{
- Variant!(int, double) variant1 = 5;
- Variant!(int, double) variant2 = 5.0;
- assert(variant1 != variant2);
-}
-
-// Uninitialized variants are equal
-@nogc nothrow pure @safe unittest
-{
- Variant!(int, double) variant1, variant2;
- assert(variant1 == variant2);
-}
-
-// Calls postblit constructor of the active type
-@nogc nothrow pure @safe unittest
-{
- static struct S
- {
- bool called;
-
- this(this)
- {
- this.called = true;
- }
- }
- Variant!(int, S) variant1 = S();
- auto variant2 = variant1;
- assert(variant2.get!S.called);
-}
-
-// Variant.type is null if the Variant doesn't have a value
-@nogc nothrow pure @safe unittest
-{
- Variant!(int, uint) variant;
- assert(variant.type is null);
-}
-
-// Variant can contain only distinct types
-@nogc nothrow pure @safe unittest
-{
- static assert(!is(Variant!(int, int)));
-}