Merge os, middle and meta subpackages
This commit is contained in:
@@ -3,11 +3,6 @@
|
||||
"description": "Runtime, middle-level utilities",
|
||||
"targetType": "library",
|
||||
|
||||
"dependencies": {
|
||||
"tanya:meta": "*",
|
||||
"tanya:os": "*"
|
||||
},
|
||||
|
||||
"dependencies-linux": {
|
||||
"mir-linux-kernel": "~>1.0.0"
|
||||
},
|
||||
|
@@ -17,9 +17,9 @@
|
||||
*/
|
||||
module tanya.memory.allocator;
|
||||
|
||||
import std.traits : hasElaborateDestructor, isAssociativeArray, isArray;
|
||||
import std.traits;
|
||||
import tanya.memory.lifetime;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta;
|
||||
|
||||
/**
|
||||
* Abstract class implementing a basic allocator.
|
||||
|
@@ -14,11 +14,10 @@
|
||||
*/
|
||||
module tanya.memory.lifetime;
|
||||
|
||||
import std.traits : isInnerClass, hasElaborateAssign, hasElaborateCopyConstructor, hasElaborateDestructor,
|
||||
isAssignable, isNested, isAbstractClass, isAggregateType, isStaticArray;
|
||||
import std.traits;
|
||||
import std.meta : AliasSeq;
|
||||
import tanya.memory.allocator;
|
||||
import tanya.meta.metafunction;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta;
|
||||
|
||||
package(tanya) void destroyAllImpl(R, E)(R p)
|
||||
{
|
||||
|
@@ -23,10 +23,10 @@
|
||||
*/
|
||||
module tanya.memory.smartref;
|
||||
|
||||
import std.traits : isPointer, isAbstractClass, isAssociativeArray, isDynamicArray, isArray;
|
||||
import std.traits;
|
||||
import tanya.memory.allocator;
|
||||
import tanya.memory.lifetime;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta;
|
||||
|
||||
private template Payload(T)
|
||||
{
|
||||
|
920
middle/tanya/meta.d
Normal file
920
middle/tanya/meta.d
Normal file
@@ -0,0 +1,920 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Template metaprogramming.
|
||||
*
|
||||
* This package contains utilities to acquire type information at compile-time,
|
||||
* to transform from one type to another. It has also different algorithms for
|
||||
* iterating, searching and modifying template arguments.
|
||||
*
|
||||
* Copyright: Eugene Wissner 2017-2025.
|
||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||
* Mozilla Public License, v. 2.0).
|
||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/package.d,
|
||||
* tanya/meta/package.d)
|
||||
*/
|
||||
module tanya.meta;
|
||||
|
||||
import std.meta;
|
||||
import std.traits;
|
||||
|
||||
/**
|
||||
* Determines whether $(D_PARAM T) is a wide string, i.e. consists of
|
||||
* $(D_KEYWORD dchar).
|
||||
*
|
||||
* The character type of the string and the string itself can have any type
|
||||
* qualifiers.
|
||||
*
|
||||
* Static $(D_KEYWORD dchar) arrays are not considered strings.
|
||||
*
|
||||
* Params:
|
||||
* T = A type.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a wide string,
|
||||
* $(D_KEYWORD false) otherwise.
|
||||
*/
|
||||
enum bool isWideString(T) = is(immutable T == immutable dchar[]);
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
static assert(isWideString!(dchar[]));
|
||||
static assert(!isWideString!(char[]));
|
||||
static assert(!isWideString!(wchar[]));
|
||||
|
||||
static assert(isWideString!dstring);
|
||||
static assert(!isWideString!string);
|
||||
static assert(!isWideString!wstring);
|
||||
|
||||
static assert(isWideString!(const dstring));
|
||||
static assert(!isWideString!(const string));
|
||||
static assert(!isWideString!(const wstring));
|
||||
|
||||
static assert(isWideString!(shared dstring));
|
||||
static assert(!isWideString!(shared string));
|
||||
static assert(!isWideString!(shared wstring));
|
||||
|
||||
static assert(isWideString!(const(dchar)[]));
|
||||
static assert(isWideString!(inout(dchar)[]));
|
||||
static assert(isWideString!(shared(const(dchar))[]));
|
||||
static assert(isWideString!(shared(dchar)[]));
|
||||
static assert(!isWideString!(dchar[10]));
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests whether $(D_PARAM T) is an interface.
|
||||
*
|
||||
* Params:
|
||||
* T = A type.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is an interface,
|
||||
* $(D_KEYWORD false) otherwise.
|
||||
*/
|
||||
private enum bool isInterface(T) = is(T == interface);
|
||||
|
||||
/**
|
||||
* Determines whether $(D_PARAM T) is a polymorphic type, i.e. a
|
||||
* $(D_KEYWORD class) or an $(D_KEYWORD interface).
|
||||
*
|
||||
* Params:
|
||||
* T = A type.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a $(D_KEYWORD class) or an
|
||||
* $(D_KEYWORD interface), $(D_KEYWORD false) otherwise.
|
||||
*/
|
||||
enum bool isPolymorphicType(T) = is(T == class) || is(T == interface);
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
interface I
|
||||
{
|
||||
}
|
||||
static assert(isPolymorphicType!Object);
|
||||
static assert(isPolymorphicType!I);
|
||||
static assert(!isPolymorphicType!short);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size in bytes of the state that needs to be allocated to hold an
|
||||
* object of type $(D_PARAM T).
|
||||
*
|
||||
* There is a difference between the `.sizeof`-property and
|
||||
* $(D_PSYMBOL stateSize) if $(D_PARAM T) is a class or an interface.
|
||||
* `T.sizeof` is constant on the given architecture then and is the same as
|
||||
* `size_t.sizeof` and `ptrdiff_t.sizeof`. This is because classes and
|
||||
* interfaces are reference types and `.sizeof` returns the size of the
|
||||
* reference which is the same as the size of a pointer. $(D_PSYMBOL stateSize)
|
||||
* returns the size of the instance itself.
|
||||
*
|
||||
* The size of a dynamic array is `size_t.sizeof * 2` since a dynamic array
|
||||
* stores its length and a data pointer. The size of the static arrays is
|
||||
* calculated differently since they are value types. It is the array length
|
||||
* multiplied by the element size.
|
||||
*
|
||||
* `stateSize!void` is `1` since $(D_KEYWORD void) is mostly used as a synonym
|
||||
* for $(D_KEYWORD byte)/$(D_KEYWORD ubyte) in `void*`.
|
||||
*
|
||||
* Params:
|
||||
* T = Object type.
|
||||
*
|
||||
* Returns: Size of an instance of type $(D_PARAM T).
|
||||
*/
|
||||
template stateSize(T)
|
||||
{
|
||||
static if (isPolymorphicType!T)
|
||||
{
|
||||
enum size_t stateSize = __traits(classInstanceSize, T);
|
||||
}
|
||||
else
|
||||
{
|
||||
enum size_t stateSize = T.sizeof;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
static assert(stateSize!int == 4);
|
||||
static assert(stateSize!bool == 1);
|
||||
static assert(stateSize!(int[]) == (size_t.sizeof * 2));
|
||||
static assert(stateSize!(short[3]) == 6);
|
||||
|
||||
static struct Empty
|
||||
{
|
||||
}
|
||||
static assert(stateSize!Empty == 1);
|
||||
static assert(stateSize!void == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the minimum value in $(D_PARAM Args) according to $(D_PARAM pred).
|
||||
*
|
||||
* $(D_PARAM Args) should contain at least one element.
|
||||
*
|
||||
* $(D_PARAM pred) can evaluate to:
|
||||
* $(UL
|
||||
* $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
|
||||
* $(D_INLINECODE Args[0] < Args[1]).)
|
||||
* $(LI $(D_KEYWORD int): a negative number means that
|
||||
* $(D_INLINECODE Args[0] < Args[1]), a positive number that
|
||||
* $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.)
|
||||
* )
|
||||
*
|
||||
* Params:
|
||||
* pred = Template predicate.
|
||||
* Args = Elements for which you want to find the minimum value.
|
||||
*
|
||||
* Returns: The minimum.
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL isLess).
|
||||
*/
|
||||
template Min(alias pred, Args...)
|
||||
if (Args.length > 0 && __traits(isTemplate, pred))
|
||||
{
|
||||
static if (Args.length == 1)
|
||||
{
|
||||
alias Min = Alias!(Args[0]);
|
||||
}
|
||||
else static if (isLess!(pred, Args[1], Args[0]))
|
||||
{
|
||||
alias Min = Min!(pred, Args[1], Args[2 .. $]);
|
||||
}
|
||||
else
|
||||
{
|
||||
alias Min = Min!(pred, Args[0], Args[2 .. $]);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
enum bool cmp(alias T, alias U) = T < U;
|
||||
static assert(Min!(cmp, 8, 4, 5, 3, 13) == 3);
|
||||
static assert(Min!(cmp, 8) == 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the maximum value in $(D_PARAM Args) according to $(D_PARAM pred).
|
||||
*
|
||||
* $(D_PARAM Args) should contain at least one element.
|
||||
*
|
||||
* $(D_PARAM pred) can evaluate to:
|
||||
* $(UL
|
||||
* $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
|
||||
* $(D_INLINECODE Args[0] < Args[1]).)
|
||||
* $(LI $(D_KEYWORD int): a negative number means that
|
||||
* $(D_INLINECODE Args[0] < Args[1]), a positive number that
|
||||
* $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.)
|
||||
* )
|
||||
*
|
||||
* Params:
|
||||
* pred = Template predicate.
|
||||
* Args = Elements for which you want to find the maximum value.
|
||||
*
|
||||
* Returns: The maximum.
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL isLess).
|
||||
*/
|
||||
template Max(alias pred, Args...)
|
||||
if (Args.length > 0 && __traits(isTemplate, pred))
|
||||
{
|
||||
static if (Args.length == 1)
|
||||
{
|
||||
alias Max = Alias!(Args[0]);
|
||||
}
|
||||
else static if (isGreater!(pred, Args[1], Args[0]))
|
||||
{
|
||||
alias Max = Max!(pred, Args[1], Args[2 .. $]);
|
||||
}
|
||||
else
|
||||
{
|
||||
alias Max = Max!(pred, Args[0], Args[2 .. $]);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
enum bool cmp(alias T, alias U) = T < U;
|
||||
static assert(Max!(cmp, 8, 4, 5, 3, 13) == 13);
|
||||
static assert(Max!(cmp, 8) == 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Zips one or more $(D_PSYMBOL Pack)s with $(D_PARAM f).
|
||||
*
|
||||
* Given $(D_PARAM f) and tuples t1, t2, ..., tk, where tk[i] denotes the
|
||||
* $(I i)-th element of the tuple $(I k)-th tuple, $(D_PSYMBOL ZipWith)
|
||||
* produces a sequence:
|
||||
*
|
||||
* ---
|
||||
* f(t1[0], t2[0], ... tk[0]),
|
||||
* f(t1[1], t2[1], ... tk[1]),
|
||||
* ...
|
||||
* f(tk[0], tk[1], ... tk[i]),
|
||||
* ---
|
||||
*
|
||||
* $(D_PSYMBOL ZipWith) begins with the first elements from $(D_PARAM Packs)
|
||||
* and applies $(D_PARAM f) to them, then it takes the second
|
||||
* ones and does the same, and so on.
|
||||
*
|
||||
* If not all argument tuples have the same length, $(D_PSYMBOL ZipWith) will
|
||||
* zip only `n` elements from each tuple, where `n` is the length of the
|
||||
* shortest tuple in the argument list. Remaining elements in the longer tuples
|
||||
* are just ignored.
|
||||
*
|
||||
* Params:
|
||||
* f = Some template that can be applied to the elements of
|
||||
* $(D_PARAM Packs).
|
||||
* Packs = $(D_PSYMBOL Pack) instances.
|
||||
*
|
||||
* Returns: A sequence, whose $(I i)-th element contains the $(I i)-th element
|
||||
* from each of the $(D_PARAM Packs).
|
||||
*/
|
||||
template ZipWith(alias f, Packs...)
|
||||
if (Packs.length > 0
|
||||
&& __traits(isTemplate, f)
|
||||
&& (allSatisfy!(ApplyLeft!(isInstanceOf, Pack), Packs)
|
||||
|| allSatisfy!(ApplyLeft!(isInstanceOf, Tuple), Packs)))
|
||||
{
|
||||
private template GetIth(size_t i, Args...)
|
||||
{
|
||||
static if ((Args.length == 0) || (Args[0].Seq.length <= i))
|
||||
{
|
||||
alias GetIth = AliasSeq!();
|
||||
}
|
||||
else
|
||||
{
|
||||
alias GetIth = AliasSeq!(Args[0].Seq[i], GetIth!(i, Args[1 .. $]));
|
||||
}
|
||||
}
|
||||
private template Iterate(size_t i, Args...)
|
||||
{
|
||||
alias Pack = GetIth!(i, Args);
|
||||
|
||||
static if (Pack.length < Packs.length)
|
||||
{
|
||||
alias Iterate = AliasSeq!();
|
||||
}
|
||||
else
|
||||
{
|
||||
alias Iterate = AliasSeq!(f!Pack, Iterate!(i + 1, Args));
|
||||
}
|
||||
}
|
||||
alias ZipWith = Iterate!(0, Packs);
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
alias Result1 = ZipWith!(AliasSeq, Pack!(1, 2), Pack!(5, 6), Pack!(9, 10));
|
||||
static assert(Result1 == AliasSeq!(1, 5, 9, 2, 6, 10));
|
||||
|
||||
alias Result2 = ZipWith!(AliasSeq, Pack!(1, 2, 3), Pack!(4, 5));
|
||||
static assert(Result2 == AliasSeq!(1, 4, 2, 5));
|
||||
|
||||
alias Result3 = ZipWith!(AliasSeq, Pack!(), Pack!(4, 5));
|
||||
static assert(Result3.length == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds a typed sequence of template parameters.
|
||||
*
|
||||
* Different than $(D_PSYMBOL AliasSeq), $(D_PSYMBOL Pack) doesn't unpack
|
||||
* its template parameters automatically. Consider:
|
||||
*
|
||||
* ---
|
||||
* template A(Args...)
|
||||
* {
|
||||
* static assert(Args.length == 4);
|
||||
* }
|
||||
*
|
||||
* alias AInstance = A!(AliasSeq!(int, uint), AliasSeq!(float, double));
|
||||
* ---
|
||||
*
|
||||
* Using $(D_PSYMBOL AliasSeq) template `A` gets 4 parameters instead of 2,
|
||||
* because $(D_PSYMBOL AliasSeq) is just an alias for its template parameters.
|
||||
*
|
||||
* With $(D_PSYMBOL Pack) it is possible to pass distinguishable
|
||||
* sequences of parameters to a template. So:
|
||||
*
|
||||
* ---
|
||||
* template B(Args...)
|
||||
* {
|
||||
* static assert(Args.length == 2);
|
||||
* }
|
||||
*
|
||||
* alias BInstance = B!(Pack!(int, uint), Pack!(float, double));
|
||||
* ---
|
||||
*
|
||||
* Params:
|
||||
* Args = Elements of this $(D_PSYMBOL Pack).
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL AliasSeq).
|
||||
*/
|
||||
struct Pack(Args...)
|
||||
{
|
||||
/// Elements in this tuple as $(D_PSYMBOL AliasSeq).
|
||||
alias Seq = Args;
|
||||
|
||||
/// The length of the tuple.
|
||||
enum size_t length = Args.length;
|
||||
|
||||
alias Seq this;
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
alias A = Pack!short;
|
||||
alias B = Pack!(3, 8, 9);
|
||||
alias C = Pack!(A, B);
|
||||
|
||||
static assert(C.length == 2);
|
||||
|
||||
static assert(A.length == 1);
|
||||
static assert(is(A.Seq == AliasSeq!short));
|
||||
static assert(B.length == 3);
|
||||
static assert(B.Seq == AliasSeq!(3, 8, 9));
|
||||
|
||||
alias D = Pack!();
|
||||
static assert(D.length == 0);
|
||||
static assert(is(D.Seq == AliasSeq!()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unordered sequence of unique aliases.
|
||||
*
|
||||
* $(D_PARAM Args) can contain duplicates, but they will be filtered out, so
|
||||
* $(D_PSYMBOL Set) contains only unique items. $(D_PSYMBOL isEqual) is used
|
||||
* for determining if two items are equal.
|
||||
*
|
||||
* Params:
|
||||
* Args = Elements of this $(D_PSYMBOL Set).
|
||||
*/
|
||||
struct Set(Args...)
|
||||
{
|
||||
/// Elements in this set as $(D_PSYMBOL AliasSeq).
|
||||
alias Seq = NoDuplicates!Args;
|
||||
|
||||
/// The length of the set.
|
||||
enum size_t length = Seq.length;
|
||||
|
||||
alias Seq this;
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
alias S1 = Set!(int, 5, 5, int, 4);
|
||||
static assert(S1.length == 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a $(D_PSYMBOL Set) containing all elements of the given
|
||||
* $(D_PARAM Sets).
|
||||
*
|
||||
* Params:
|
||||
* Sets = List of $(D_PSYMBOL Set) instances.
|
||||
*
|
||||
* Returns: Set-theoretic union of all $(D_PARAM Sets).
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL Set).
|
||||
*/
|
||||
template Union(Sets...)
|
||||
if (allSatisfy!(ApplyLeft!(isInstanceOf, Set), Sets))
|
||||
{
|
||||
private template Impl(Sets...)
|
||||
{
|
||||
static if (Sets.length == 0)
|
||||
{
|
||||
alias Impl = AliasSeq!();
|
||||
}
|
||||
else
|
||||
{
|
||||
alias Impl = AliasSeq!(Sets[0].Seq, Impl!(Sets[1 .. $]));
|
||||
}
|
||||
}
|
||||
alias Union = Set!(Impl!Sets);
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
alias S1 = Set!(2, 5, 8, 4);
|
||||
alias S2 = Set!(3, 8, 4, 1);
|
||||
static assert(Union!(S1, S2).Seq == AliasSeq!(2, 5, 8, 4, 3, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a $(D_PSYMBOL Set) that containing elements of
|
||||
* $(D_INLINECODE Sets[0]) that are also elements of all other sets in
|
||||
* $(D_PARAM Sets).
|
||||
*
|
||||
* Params:
|
||||
* Sets = List of $(D_PSYMBOL Set) instances.
|
||||
*
|
||||
* Returns: Set-theoretic intersection of all $(D_PARAM Sets).
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL Set).
|
||||
*/
|
||||
template Intersection(Sets...)
|
||||
if (allSatisfy!(ApplyLeft!(isInstanceOf, Set), Sets))
|
||||
{
|
||||
private template Impl(Args...)
|
||||
if (Args.length > 0)
|
||||
{
|
||||
alias Equal = ApplyLeft!(isEqual, Args[0]);
|
||||
static if (Args.length == 1)
|
||||
{
|
||||
enum bool Impl = true;
|
||||
}
|
||||
else static if (!anySatisfy!(Equal, Args[1].Seq))
|
||||
{
|
||||
enum bool Impl = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
enum bool Impl = Impl!(Args[0], Args[2 .. $]);
|
||||
}
|
||||
}
|
||||
|
||||
private enum bool FilterImpl(Args...) = Impl!(Args[0], Sets[1 .. $]);
|
||||
|
||||
static if (Sets.length == 0)
|
||||
{
|
||||
alias Intersection = Set!();
|
||||
}
|
||||
else
|
||||
{
|
||||
alias Intersection = Set!(Filter!(FilterImpl, Sets[0].Seq));
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
alias S1 = Set!(2, 5, 8, 4);
|
||||
alias S2 = Set!(3, 8, 4, 1);
|
||||
static assert(Intersection!(S1, S2).Seq == AliasSeq!(8, 4));
|
||||
|
||||
static assert(Intersection!(S1).Seq == AliasSeq!(2, 5, 8, 4));
|
||||
static assert(Intersection!().length == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a $(D_PSYMBOL Set) that contains all elements of
|
||||
* $(D_PARAM S1) that are not members of $(D_PARAM S2).
|
||||
*
|
||||
* Params:
|
||||
* S1 = A $(D_PSYMBOL Set).
|
||||
* S2 = A $(D_PSYMBOL Set).
|
||||
*
|
||||
* Returns: Set-theoretic difference of two sets $(D_PARAM S1) and
|
||||
* $(D_PARAM S2).
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL Set).
|
||||
*/
|
||||
template Difference(alias S1, alias S2)
|
||||
if (isInstanceOf!(Set, S1) && isInstanceOf!(Set, S2))
|
||||
{
|
||||
private template Impl(Args...)
|
||||
{
|
||||
alias Equal = ApplyLeft!(isEqual, Args[0]);
|
||||
enum bool Impl = !anySatisfy!(Equal, S2.Seq);
|
||||
}
|
||||
|
||||
static if (S1.length == 0)
|
||||
{
|
||||
alias Difference = Set!();
|
||||
}
|
||||
else static if (S2.length == 1)
|
||||
{
|
||||
alias Difference = S1;
|
||||
}
|
||||
else
|
||||
{
|
||||
alias Difference = Set!(Filter!(Impl, S1.Seq));
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
alias S1 = Set!(2, 5, 8, 4);
|
||||
alias S2 = Set!(3, 8, 4, 1);
|
||||
static assert(Difference!(S1, S2).Seq == AliasSeq!(2, 5));
|
||||
static assert(Difference!(S2, S1).Seq == AliasSeq!(3, 1));
|
||||
static assert(Difference!(S1, Set!()).Seq == AliasSeq!(2, 5, 8, 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether $(D_INLINECODE Args[0]) is less than or equal to
|
||||
* $(D_INLINECODE Args[1]) according to $(D_PARAM cmp).
|
||||
*
|
||||
* $(D_PARAM cmp) can evaluate to:
|
||||
* $(UL
|
||||
* $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
|
||||
* $(D_INLINECODE Args[0] < Args[1]).)
|
||||
* $(LI $(D_KEYWORD int): a negative number means that
|
||||
* $(D_INLINECODE Args[0] < Args[1]), a positive number that
|
||||
* $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.)
|
||||
* )
|
||||
*
|
||||
* Params:
|
||||
* Args = Two aliases to compare for equality.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if $(D_INLINECODE Args[0]) is less than or equal
|
||||
* to $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
|
||||
*/
|
||||
template isLessEqual(alias cmp, Args...)
|
||||
if (Args.length == 2 && __traits(isTemplate, cmp))
|
||||
{
|
||||
private enum result = cmp!(Args[1], Args[0]);
|
||||
static if (is(typeof(result) == bool))
|
||||
{
|
||||
enum bool isLessEqual = !result;
|
||||
}
|
||||
else
|
||||
{
|
||||
enum bool isLessEqual = result >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
enum bool boolCmp(T, U) = T.sizeof < U.sizeof;
|
||||
static assert(isLessEqual!(boolCmp, byte, int));
|
||||
static assert(isLessEqual!(boolCmp, uint, int));
|
||||
static assert(!isLessEqual!(boolCmp, long, int));
|
||||
|
||||
enum ptrdiff_t intCmp(T, U) = T.sizeof - U.sizeof;
|
||||
static assert(isLessEqual!(intCmp, byte, int));
|
||||
static assert(isLessEqual!(intCmp, uint, int));
|
||||
static assert(!isLessEqual!(intCmp, long, int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether $(D_INLINECODE Args[0]) is greater than or equal to
|
||||
* $(D_INLINECODE Args[1]) according to $(D_PARAM cmp).
|
||||
*
|
||||
* $(D_PARAM cmp) can evaluate to:
|
||||
* $(UL
|
||||
* $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
|
||||
* $(D_INLINECODE Args[0] < Args[1]).)
|
||||
* $(LI $(D_KEYWORD int): a negative number means that
|
||||
* $(D_INLINECODE Args[0] < Args[1]), a positive number that
|
||||
* $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.)
|
||||
* )
|
||||
*
|
||||
* Params:
|
||||
* Args = Two aliases to compare for equality.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if $(D_INLINECODE Args[0]) is greater than or
|
||||
* equal to $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
|
||||
*/
|
||||
template isGreaterEqual(alias cmp, Args...)
|
||||
if (Args.length == 2 && __traits(isTemplate, cmp))
|
||||
{
|
||||
private enum result = cmp!Args;
|
||||
static if (is(typeof(result) == bool))
|
||||
{
|
||||
enum bool isGreaterEqual = !result;
|
||||
}
|
||||
else
|
||||
{
|
||||
enum bool isGreaterEqual = result >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
enum bool boolCmp(T, U) = T.sizeof < U.sizeof;
|
||||
static assert(!isGreaterEqual!(boolCmp, byte, int));
|
||||
static assert(isGreaterEqual!(boolCmp, uint, int));
|
||||
static assert(isGreaterEqual!(boolCmp, long, int));
|
||||
|
||||
enum ptrdiff_t intCmp(T, U) = T.sizeof - U.sizeof;
|
||||
static assert(!isGreaterEqual!(intCmp, byte, int));
|
||||
static assert(isGreaterEqual!(intCmp, uint, int));
|
||||
static assert(isGreaterEqual!(intCmp, long, int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether $(D_INLINECODE Args[0]) is less than
|
||||
* $(D_INLINECODE Args[1]) according to $(D_PARAM cmp).
|
||||
*
|
||||
* $(D_PARAM cmp) can evaluate to:
|
||||
* $(UL
|
||||
* $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
|
||||
* $(D_INLINECODE Args[0] < Args[1]).)
|
||||
* $(LI $(D_KEYWORD int): a negative number means that
|
||||
* $(D_INLINECODE Args[0] < Args[1]), a positive number that
|
||||
* $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.)
|
||||
* )
|
||||
*
|
||||
* Params:
|
||||
* Args = Two aliases to compare for equality.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if $(D_INLINECODE Args[0]) is less than
|
||||
* $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
|
||||
*/
|
||||
template isLess(alias cmp, Args...)
|
||||
if (Args.length == 2 && __traits(isTemplate, cmp))
|
||||
{
|
||||
private enum result = cmp!Args;
|
||||
static if (is(typeof(result) == bool))
|
||||
{
|
||||
enum bool isLess = result;
|
||||
}
|
||||
else
|
||||
{
|
||||
enum bool isLess = result < 0;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
enum bool boolCmp(T, U) = T.sizeof < U.sizeof;
|
||||
static assert(isLess!(boolCmp, byte, int));
|
||||
static assert(!isLess!(boolCmp, uint, int));
|
||||
static assert(!isLess!(boolCmp, long, int));
|
||||
|
||||
enum ptrdiff_t intCmp(T, U) = T.sizeof - U.sizeof;
|
||||
static assert(isLess!(intCmp, byte, int));
|
||||
static assert(!isLess!(intCmp, uint, int));
|
||||
static assert(!isLess!(intCmp, long, int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether $(D_INLINECODE Args[0]) is greater than
|
||||
* $(D_INLINECODE Args[1]) according to $(D_PARAM cmp).
|
||||
*
|
||||
* $(D_PARAM cmp) can evaluate to:
|
||||
* $(UL
|
||||
* $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
|
||||
* $(D_INLINECODE Args[0] < Args[1]).)
|
||||
* $(LI $(D_KEYWORD int): a negative number means that
|
||||
* $(D_INLINECODE Args[0] < Args[1]), a positive number that
|
||||
* $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.)
|
||||
* )
|
||||
*
|
||||
* Params:
|
||||
* Args = Two aliases to compare for equality.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if $(D_INLINECODE Args[0]) is greater than
|
||||
* $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
|
||||
*/
|
||||
template isGreater(alias cmp, Args...)
|
||||
if (Args.length == 2 && __traits(isTemplate, cmp))
|
||||
{
|
||||
private enum result = cmp!Args;
|
||||
static if (is(typeof(result) == bool))
|
||||
{
|
||||
enum bool isGreater = !result && cmp!(Args[1], Args[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
enum bool isGreater = result > 0;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
enum bool boolCmp(T, U) = T.sizeof < U.sizeof;
|
||||
static assert(!isGreater!(boolCmp, byte, int));
|
||||
static assert(!isGreater!(boolCmp, uint, int));
|
||||
static assert(isGreater!(boolCmp, long, int));
|
||||
|
||||
enum ptrdiff_t intCmp(T, U) = T.sizeof - U.sizeof;
|
||||
static assert(!isGreater!(intCmp, byte, int));
|
||||
static assert(!isGreater!(intCmp, uint, int));
|
||||
static assert(isGreater!(intCmp, long, int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether $(D_INLINECODE Args[0]) is equal to $(D_INLINECODE Args[1]).
|
||||
*
|
||||
* $(D_PSYMBOL isEqual) checks first if $(D_PARAM Args) can be compared directly. If not, they are compared as types:
|
||||
* $(D_INLINECODE is(Args[0] == Args[1])). It it fails, the arguments are
|
||||
* considered to be not equal.
|
||||
*
|
||||
* If two items cannot be compared (for example comparing a type with a
|
||||
* number), they are considered not equal.
|
||||
*
|
||||
* Params:
|
||||
* Args = Two aliases to compare for equality.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if $(D_INLINECODE Args[0]) is equal to
|
||||
* $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
|
||||
*/
|
||||
template isEqual(Args...)
|
||||
if (Args.length == 2)
|
||||
{
|
||||
static if ((is(typeof(Args[0] == Args[1])) && (Args[0] == Args[1]))
|
||||
|| (isTypeTuple!Args && is(Args[0] == Args[1]))
|
||||
|| __traits(isSame, Args[0], Args[1]))
|
||||
{
|
||||
enum bool isEqual = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
enum bool isEqual = false;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
static assert(isEqual!(int, int));
|
||||
static assert(isEqual!(8, 8));
|
||||
static assert(!isEqual!(int, const(int)));
|
||||
static assert(!isEqual!(5, int));
|
||||
static assert(!isEqual!(5, 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether $(D_INLINECODE Args[0]) isn't equal to
|
||||
* $(D_INLINECODE Args[1]).
|
||||
*
|
||||
* $(D_PSYMBOL isNotEqual) checks first if $(D_PARAM Args) can be compared directly. If not, they are compared as types:
|
||||
* $(D_INLINECODE is(Args[0] == Args[1])). It it fails, the arguments are
|
||||
* considered to be not equal.
|
||||
*
|
||||
* Params:
|
||||
* Args = Two aliases to compare for equality.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if $(D_INLINECODE Args[0]) isn't equal to
|
||||
* $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
|
||||
*/
|
||||
template isNotEqual(Args...)
|
||||
if (Args.length == 2)
|
||||
{
|
||||
enum bool isNotEqual = !isEqual!Args;
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
static assert(!isNotEqual!(int, int));
|
||||
static assert(isNotEqual!(5, int));
|
||||
static assert(isNotEqual!(5, 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for $(D_PARAM T) in $(D_PARAM L) and returns $(D_KEYWORD true) if it
|
||||
* could be found and $(D_KEYWORD false) otherwise.
|
||||
*
|
||||
* Params:
|
||||
* T = The item to search for.
|
||||
* L = Symbol sequence.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if $(D_PARAM T) can be found in $(D_PARAM L),
|
||||
* $(D_KEYWORD false) otherwise.
|
||||
*/
|
||||
enum bool canFind(T, L...) = staticIndexOf!(T, L) != -1;
|
||||
|
||||
/// ditto
|
||||
enum bool canFind(alias T, L...) = staticIndexOf!(T, L) != -1;
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
static assert(!canFind!(int));
|
||||
static assert(canFind!(int, int));
|
||||
static assert(canFind!(int, float, double, int, real));
|
||||
static assert(canFind!(3, () {}, uint, 5, 3));
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests whether $(D_PARAM T) is a template.
|
||||
*
|
||||
* $(D_PSYMBOL isTemplate) isn't $(D_KEYWORD true) for template instances,
|
||||
* since the latter already represent some type. Only not instantiated
|
||||
* templates, i.e. that accept some template parameters, are considered
|
||||
* templates.
|
||||
*
|
||||
* Params:
|
||||
* T = A symbol.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a template,
|
||||
* $(D_KEYWORD false) otherwise.
|
||||
*/
|
||||
enum bool isTemplate(alias T) = __traits(isTemplate, T);
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
static struct S(T)
|
||||
{
|
||||
}
|
||||
static assert(isTemplate!S);
|
||||
static assert(!isTemplate!(S!int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches a numeric index to each element from $(D_PARAM Args).
|
||||
*
|
||||
* $(D_PSYMBOL EnumerateFrom) returns a sequence of tuples ($(D_PSYMBOL Pack)s)
|
||||
* consisting of the index of each element and the element itself.
|
||||
*
|
||||
* Params:
|
||||
* start = Enumeration initial value.
|
||||
* Args = Enumerated sequence.
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL Enumerate).
|
||||
*/
|
||||
template EnumerateFrom(size_t start, Args...)
|
||||
{
|
||||
static if (Args.length == 0)
|
||||
{
|
||||
alias EnumerateFrom = AliasSeq!();
|
||||
}
|
||||
else
|
||||
{
|
||||
alias EnumerateFrom = AliasSeq!(Pack!(start, Args[0]), EnumerateFrom!(start + 1, Args[1 .. $]));
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
static assert(EnumerateFrom!(0, int, uint, bool).length == 3);
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
alias Expected = AliasSeq!(Pack!(cast(size_t) 0, int),
|
||||
Pack!(cast(size_t) 1, uint));
|
||||
static assert(is(EnumerateFrom!(0, int, uint) == Expected));
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches a numeric index to each element from $(D_PARAM Args).
|
||||
*
|
||||
* $(D_PSYMBOL EnumerateFrom) returns a sequence of tuples ($(D_PSYMBOL Pack)s)
|
||||
* consisting of the index of each element and the element itself.
|
||||
*
|
||||
* Params:
|
||||
* Args = Enumerated sequence.
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL EnumerateFrom).
|
||||
*/
|
||||
alias Enumerate(Args...) = EnumerateFrom!(0, Args);
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
alias Expected = AliasSeq!(Pack!(cast(size_t) 0, int),
|
||||
Pack!(cast(size_t) 1, uint));
|
||||
static assert(is(Enumerate!(int, uint) == Expected));
|
||||
}
|
413
middle/tanya/os/error.d
Normal file
413
middle/tanya/os/error.d
Normal file
@@ -0,0 +1,413 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* This module provides a portable way of using operating system error codes.
|
||||
*
|
||||
* Copyright: Eugene Wissner 2017-2025.
|
||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||
* Mozilla Public License, v. 2.0).
|
||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/os/tanya/os/error.d,
|
||||
* tanya/os/error.d)
|
||||
*/
|
||||
module tanya.os.error;
|
||||
|
||||
import tanya.meta;
|
||||
|
||||
// Socket API error.
|
||||
private template SAError(int posix, int wsa = posix)
|
||||
{
|
||||
version (Windows)
|
||||
{
|
||||
enum SAError = 10000 + wsa;
|
||||
}
|
||||
else
|
||||
{
|
||||
alias SAError = posix;
|
||||
}
|
||||
}
|
||||
|
||||
// Error for Windows and Posix separately.
|
||||
private template NativeError(int posix, int win)
|
||||
{
|
||||
version (Windows)
|
||||
{
|
||||
alias NativeError = win;
|
||||
}
|
||||
else
|
||||
{
|
||||
alias NativeError = posix;
|
||||
}
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
private enum eProtocolError = -71;
|
||||
}
|
||||
else version (OpenBSD)
|
||||
{
|
||||
private enum eProtocolError = -71;
|
||||
}
|
||||
else
|
||||
{
|
||||
private enum eProtocolError = 71;
|
||||
}
|
||||
|
||||
/**
|
||||
* System error code.
|
||||
*/
|
||||
struct ErrorCode
|
||||
{
|
||||
/**
|
||||
* Error code numbers.
|
||||
*/
|
||||
enum ErrorNo : int
|
||||
{
|
||||
/// The operation completed successfully.
|
||||
success = 0,
|
||||
|
||||
/// Operation not permitted.
|
||||
noPermission = NativeError!(1, 5),
|
||||
|
||||
/// Interrupted system call.
|
||||
interrupted = SAError!4,
|
||||
|
||||
/// Bad file descriptor.
|
||||
badDescriptor = SAError!9,
|
||||
|
||||
/// An operation on a non-blocking socket would block.
|
||||
wouldBlock = SAError!(11, 35),
|
||||
|
||||
/// Out of memory.
|
||||
noMemory = NativeError!(12, 14),
|
||||
|
||||
/// Access denied.
|
||||
accessDenied = SAError!13,
|
||||
|
||||
/// An invalid pointer address detected.
|
||||
fault = SAError!14,
|
||||
|
||||
/// No such device.
|
||||
noSuchDevice = NativeError!(19, 20),
|
||||
|
||||
/// An invalid argument was supplied.
|
||||
invalidArgument = SAError!22,
|
||||
|
||||
/// The limit on the number of open file descriptors.
|
||||
tooManyDescriptors = NativeError!(23, 331),
|
||||
|
||||
/// The limit on the number of open file descriptors.
|
||||
noDescriptors = SAError!24,
|
||||
|
||||
/// Broken pipe.
|
||||
brokenPipe = NativeError!(32, 109),
|
||||
|
||||
/// The name was too long.
|
||||
nameTooLong = SAError!(36, 63),
|
||||
|
||||
/// A socket operation was attempted on a non-socket.
|
||||
notSocket = SAError!(88, 38),
|
||||
|
||||
/// Protocol error.
|
||||
protocolError = eProtocolError,
|
||||
|
||||
/// Message too long.
|
||||
messageTooLong = SAError!(90, 40),
|
||||
|
||||
/// Wrong protocol type for socket.
|
||||
wrongProtocolType = SAError!(91, 41),
|
||||
|
||||
/// Protocol not available.
|
||||
noProtocolOption = SAError!(92, 42),
|
||||
|
||||
/// The protocol is not implemented or has not been configured.
|
||||
protocolNotSupported = SAError!(93, 43),
|
||||
|
||||
/// The support for the specified socket type does not exist in this
|
||||
/// address family.
|
||||
socketNotSupported = SAError!(94, 44),
|
||||
|
||||
/// The address family is no supported by the protocol family.
|
||||
operationNotSupported = SAError!(95, 45),
|
||||
|
||||
/// Address family specified is not supported.
|
||||
addressFamilyNotSupported = SAError!(97, 47),
|
||||
|
||||
/// Address already in use.
|
||||
addressInUse = SAError!(98, 48),
|
||||
|
||||
/// The network is not available.
|
||||
networkDown = SAError!(100, 50),
|
||||
|
||||
/// No route to host.
|
||||
networkUnreachable = SAError!(101, 51),
|
||||
|
||||
/// Network dropped connection because of reset.
|
||||
networkReset = SAError!(102, 52),
|
||||
|
||||
/// The connection has been aborted.
|
||||
connectionAborted = SAError!(103, 53),
|
||||
|
||||
/// Connection reset by peer.
|
||||
connectionReset = SAError!(104, 54),
|
||||
|
||||
/// No free buffer space is available for a socket operation.
|
||||
noBufferSpace = SAError!(105, 55),
|
||||
|
||||
/// Transport endpoint is already connected.
|
||||
alreadyConnected = SAError!(106, 56),
|
||||
|
||||
/// Transport endpoint is not connected.
|
||||
notConnected = SAError!(107, 57),
|
||||
|
||||
/// Cannot send after transport endpoint shutdown.
|
||||
shutdown = SAError!(108, 58),
|
||||
|
||||
/// The connection attempt timed out, or the connected host has failed
|
||||
/// to respond.
|
||||
timedOut = SAError!(110, 60),
|
||||
|
||||
/// Connection refused.
|
||||
connectionRefused = SAError!(111, 61),
|
||||
|
||||
/// Host is down.
|
||||
hostDown = SAError!(112, 64),
|
||||
|
||||
/// No route to host.
|
||||
hostUnreachable = SAError!(113, 65),
|
||||
|
||||
/// Operation already in progress.
|
||||
alreadyStarted = SAError!(114, 37),
|
||||
|
||||
/// Operation now in progress.
|
||||
inProgress = SAError!(115, 36),
|
||||
|
||||
/// Operation cancelled.
|
||||
cancelled = SAError!(125, 103),
|
||||
}
|
||||
|
||||
/**
|
||||
* Error descriptions.
|
||||
*/
|
||||
private enum ErrorStr : string
|
||||
{
|
||||
success = "The operation completed successfully",
|
||||
noPermission = "Operation not permitted",
|
||||
interrupted = "Interrupted system call",
|
||||
badDescriptor = "Bad file descriptor",
|
||||
wouldBlock = "An operation on a non-blocking socket would block",
|
||||
noMemory = "Out of memory",
|
||||
accessDenied = "Access denied",
|
||||
fault = "An invalid pointer address detected",
|
||||
noSuchDevice = "No such device",
|
||||
invalidArgument = "An invalid argument was supplied",
|
||||
tooManyDescriptors = "The limit on the number of open file descriptors",
|
||||
noDescriptors = "The limit on the number of open file descriptors",
|
||||
brokenPipe = "Broken pipe",
|
||||
nameTooLong = "The name was too long",
|
||||
notSocket = "A socket operation was attempted on a non-socket",
|
||||
protocolError = "Protocol error",
|
||||
messageTooLong = "Message too long",
|
||||
wrongProtocolType = "Wrong protocol type for socket",
|
||||
noProtocolOption = "Protocol not available",
|
||||
protocolNotSupported = "The protocol is not implemented or has not been configured",
|
||||
socketNotSupported = "Socket type not supported",
|
||||
operationNotSupported = "The address family is no supported by the protocol family",
|
||||
addressFamilyNotSupported = "Address family specified is not supported",
|
||||
addressInUse = "Address already in use",
|
||||
networkDown = "The network is not available",
|
||||
networkUnreachable = "No route to host",
|
||||
networkReset = "Network dropped connection because of reset",
|
||||
connectionAborted = "The connection has been aborted",
|
||||
connectionReset = "Connection reset by peer",
|
||||
noBufferSpace = "No free buffer space is available for a socket operation",
|
||||
alreadyConnected = "Transport endpoint is already connected",
|
||||
notConnected = "Transport endpoint is not connected",
|
||||
shutdown = "Cannot send after transport endpoint shutdown",
|
||||
timedOut = "Operation timed out",
|
||||
connectionRefused = "Connection refused",
|
||||
hostDown = "Host is down",
|
||||
hostUnreachable = "No route to host",
|
||||
alreadyStarted = "Operation already in progress",
|
||||
inProgress = "Operation now in progress",
|
||||
cancelled = "Operation cancelled",
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Params:
|
||||
* value = Numeric error code.
|
||||
*/
|
||||
this(const ErrorNo value) @nogc nothrow pure @safe
|
||||
{
|
||||
this.value_ = value;
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
ErrorCode ec;
|
||||
assert(ec == ErrorCode.success);
|
||||
|
||||
ec = ErrorCode.fault;
|
||||
assert(ec == ErrorCode.fault);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets this $(D_PSYMBOL ErrorCode) to default
|
||||
* ($(D_PSYMBOL ErrorCode.success)).
|
||||
*/
|
||||
void reset() @nogc nothrow pure @safe
|
||||
{
|
||||
this.value_ = ErrorNo.success;
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
auto ec = ErrorCode(ErrorCode.fault);
|
||||
assert(ec == ErrorCode.fault);
|
||||
|
||||
ec.reset();
|
||||
assert(ec == ErrorCode.success);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns: Numeric error code.
|
||||
*/
|
||||
ErrorNo opCast(T : ErrorNo)() const
|
||||
{
|
||||
return this.value_;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
ErrorNo opCast(T : int)() const
|
||||
{
|
||||
return this.value_;
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
ErrorCode ec = ErrorCode.fault;
|
||||
auto errorNo = cast(ErrorCode.ErrorNo) ec;
|
||||
|
||||
assert(errorNo == ErrorCode.fault);
|
||||
static assert(is(typeof(cast(int) ec)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns another error code or error code number.
|
||||
*
|
||||
* Params:
|
||||
* that = Numeric error code.
|
||||
*
|
||||
* Returns: $(D_KEYWORD this).
|
||||
*/
|
||||
ref ErrorCode opAssign(const ErrorNo that) return @nogc nothrow pure @safe
|
||||
{
|
||||
this.value_ = that;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
ref ErrorCode opAssign(const ErrorCode that) return @nogc nothrow pure @safe
|
||||
{
|
||||
this.value_ = that.value_;
|
||||
return this;
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
ErrorCode ec;
|
||||
assert(ec == ErrorCode.success);
|
||||
|
||||
ec = ErrorCode.fault;
|
||||
assert(ec == ErrorCode.fault);
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
auto ec1 = ErrorCode(ErrorCode.fault);
|
||||
ErrorCode ec2;
|
||||
assert(ec2 == ErrorCode.success);
|
||||
|
||||
ec2 = ec1;
|
||||
assert(ec1 == ec2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equality with another error code or error code number.
|
||||
*
|
||||
* Params:
|
||||
* that = Numeric error code.
|
||||
*
|
||||
* Returns: Whether $(D_KEYWORD this) and $(D_PARAM that) are equal.
|
||||
*/
|
||||
bool opEquals(const ErrorNo that) const @nogc nothrow pure @safe
|
||||
{
|
||||
return this.value_ == that;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
bool opEquals(const ErrorCode that) const @nogc nothrow pure @safe
|
||||
{
|
||||
return this.value_ == that.value_;
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
ErrorCode ec1 = ErrorCode.fault;
|
||||
ErrorCode ec2 = ErrorCode.accessDenied;
|
||||
|
||||
assert(ec1 != ec2);
|
||||
assert(ec1 != ErrorCode.accessDenied);
|
||||
assert(ErrorCode.fault != ec2);
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
ErrorCode ec1 = ErrorCode.fault;
|
||||
ErrorCode ec2 = ErrorCode.fault;
|
||||
|
||||
assert(ec1 == ec2);
|
||||
assert(ec1 == ErrorCode.fault);
|
||||
assert(ErrorCode.fault == ec2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string describing the error number. If a description for a
|
||||
* specific error number is not available, returns $(D_KEYWORD null).
|
||||
*
|
||||
* Returns: String describing the error number.
|
||||
*/
|
||||
string toString() const @nogc nothrow pure @safe
|
||||
{
|
||||
foreach (e; __traits(allMembers, ErrorNo))
|
||||
{
|
||||
if (__traits(getMember, ErrorNo, e) == this.value_)
|
||||
{
|
||||
return __traits(getMember, ErrorStr, e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
ErrorCode ec = ErrorCode.fault;
|
||||
assert(ec.toString() == "An invalid pointer address detected");
|
||||
}
|
||||
|
||||
private ErrorNo value_ = ErrorNo.success;
|
||||
|
||||
alias ErrorNo this;
|
||||
}
|
18
middle/tanya/os/package.d
Normal file
18
middle/tanya/os/package.d
Normal file
@@ -0,0 +1,18 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* This package provides platform-independent interfaces to operating system
|
||||
* functionality.
|
||||
*
|
||||
* Copyright: Eugene Wissner 2017-2025.
|
||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||
* Mozilla Public License, v. 2.0).
|
||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/os/tanya/os/package.d,
|
||||
* tanya/os/package.d)
|
||||
*/
|
||||
module tanya.os;
|
||||
|
||||
public import tanya.os.error;
|
Reference in New Issue
Block a user