Add test.stub. Fix #51
This commit is contained in:
parent
0a121d9d19
commit
7585bf59e7
@ -23,7 +23,7 @@ module tanya.algorithm.iteration;
|
|||||||
import tanya.algorithm.comparison;
|
import tanya.algorithm.comparison;
|
||||||
import tanya.algorithm.mutation;
|
import tanya.algorithm.mutation;
|
||||||
import tanya.range;
|
import tanya.range;
|
||||||
version (unittest) import tanya.test.range;
|
version (unittest) import tanya.test.stub;
|
||||||
|
|
||||||
private struct Take(R, bool exactly)
|
private struct Take(R, bool exactly)
|
||||||
{
|
{
|
||||||
@ -322,10 +322,9 @@ if (isInputRange!R)
|
|||||||
// length is unknown when taking from a range without length
|
// length is unknown when taking from a range without length
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
@Empty
|
|
||||||
static struct R
|
static struct R
|
||||||
{
|
{
|
||||||
mixin InputRange;
|
mixin InputRangeStub;
|
||||||
}
|
}
|
||||||
auto actual = take(R(), 100);
|
auto actual = take(R(), 100);
|
||||||
|
|
||||||
|
@ -2856,6 +2856,46 @@ template hasUDA(alias symbol, alias attr)
|
|||||||
static assert(!hasUDA!(a, Attr2));
|
static assert(!hasUDA!(a, Attr2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If $(D_PARAM T) is a type, constructs its default value, otherwise
|
||||||
|
* $(D_PSYMBOL evalUDA) aliases itself to $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* This template is useful when working with UDAs with default parameters,
|
||||||
|
* i.e. if an attribute can be given as `@Attr` or `@Attr("param")`,
|
||||||
|
* $(D_PSYMBOL evalUDA) makes `@Attr()` from `@Attr`, but returns
|
||||||
|
* `@Attr("param")` as is.
|
||||||
|
*
|
||||||
|
* $(D_PARAM T) (or its type if it isn't a type already) should have a default
|
||||||
|
* constructor.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = User Defined Attribute.
|
||||||
|
*/
|
||||||
|
alias evalUDA(alias T) = T;
|
||||||
|
|
||||||
|
/// ditto
|
||||||
|
alias evalUDA(T) = Alias!(T());
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
static struct Length
|
||||||
|
{
|
||||||
|
size_t length = 8;
|
||||||
|
}
|
||||||
|
@Length @Length(0) int i;
|
||||||
|
alias uda = AliasSeq!(__traits(getAttributes, i));
|
||||||
|
|
||||||
|
alias attr1 = evalUDA!(uda[0]);
|
||||||
|
alias attr2 = evalUDA!(uda[1]);
|
||||||
|
|
||||||
|
static assert(is(typeof(attr1) == Length));
|
||||||
|
static assert(is(typeof(attr2) == Length));
|
||||||
|
|
||||||
|
static assert(attr1.length == 8);
|
||||||
|
static assert(attr2.length == 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests whether $(D_PARAM T) is an inner class, i.e. a class nested inside
|
* Tests whether $(D_PARAM T) is an inner class, i.e. a class nested inside
|
||||||
* another class.
|
* another class.
|
||||||
|
@ -20,6 +20,19 @@ import tanya.meta.trait;
|
|||||||
import tanya.meta.transform;
|
import tanya.meta.transform;
|
||||||
import tanya.range.array;
|
import tanya.range.array;
|
||||||
|
|
||||||
|
version (unittest)
|
||||||
|
{
|
||||||
|
import tanya.test.stub;
|
||||||
|
|
||||||
|
private struct AssertPostblit
|
||||||
|
{
|
||||||
|
this(this) @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the element type of the range $(D_PARAM R).
|
* Returns the element type of the range $(D_PARAM R).
|
||||||
*
|
*
|
||||||
@ -73,10 +86,7 @@ template ElementType(R)
|
|||||||
*
|
*
|
||||||
* See_Also: $(D_PSYMBOL isInfinite).
|
* See_Also: $(D_PSYMBOL isInfinite).
|
||||||
*/
|
*/
|
||||||
template hasLength(R)
|
enum bool hasLength(R) = is(ReturnType!((R r) => r.length) == size_t);
|
||||||
{
|
|
||||||
enum bool hasLength = is(ReturnType!((R r) => r.length) == size_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
@ -294,34 +304,6 @@ template hasSlicing(R)
|
|||||||
static assert(hasSlicing!D);
|
static assert(hasSlicing!D);
|
||||||
}
|
}
|
||||||
|
|
||||||
version (unittest)
|
|
||||||
{
|
|
||||||
mixin template InputRangeStub()
|
|
||||||
{
|
|
||||||
@property int front() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@property bool empty() const @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
void popFront() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mixin template BidirectionalRangeStub()
|
|
||||||
{
|
|
||||||
@property int back() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
void popBack() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private template isDynamicArrayRange(R)
|
private template isDynamicArrayRange(R)
|
||||||
{
|
{
|
||||||
static if (is(R E : E[]))
|
static if (is(R E : E[]))
|
||||||
@ -373,10 +355,12 @@ template isInputRange(R)
|
|||||||
void popFront() @nogc nothrow pure @safe
|
void popFront() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int front() @nogc nothrow pure @safe
|
int front() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const @nogc nothrow pure @safe
|
bool empty() const @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -391,13 +375,8 @@ template isInputRange(R)
|
|||||||
{
|
{
|
||||||
static struct Range1(T)
|
static struct Range1(T)
|
||||||
{
|
{
|
||||||
void popFront()
|
mixin InputRangeStub;
|
||||||
{
|
|
||||||
}
|
|
||||||
int front()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
T empty() const
|
T empty() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -408,45 +387,29 @@ template isInputRange(R)
|
|||||||
|
|
||||||
static struct Range2
|
static struct Range2
|
||||||
{
|
{
|
||||||
|
mixin InputRangeStub;
|
||||||
|
|
||||||
int popFront() @nogc nothrow pure @safe
|
int popFront() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
int front() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return 100;
|
|
||||||
}
|
|
||||||
bool empty() const @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static assert(isInputRange!Range2);
|
static assert(isInputRange!Range2);
|
||||||
|
|
||||||
static struct Range3
|
static struct Range3
|
||||||
{
|
{
|
||||||
void popFront() @nogc nothrow pure @safe
|
mixin InputRangeStub;
|
||||||
{
|
|
||||||
}
|
|
||||||
void front() @nogc nothrow pure @safe
|
void front() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
bool empty() const @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static assert(!isInputRange!Range3);
|
static assert(!isInputRange!Range3);
|
||||||
|
|
||||||
static struct Range4
|
static struct Range4
|
||||||
{
|
{
|
||||||
void popFront() @nogc nothrow pure @safe
|
mixin InputRangeStub;
|
||||||
{
|
|
||||||
}
|
|
||||||
int front() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
enum bool empty = false;
|
enum bool empty = false;
|
||||||
}
|
}
|
||||||
static assert(isInputRange!Range4);
|
static assert(isInputRange!Range4);
|
||||||
@ -489,14 +452,17 @@ template isForwardRange(R)
|
|||||||
void popFront() @nogc nothrow pure @safe
|
void popFront() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int front() @nogc nothrow pure @safe
|
int front() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const @nogc nothrow pure @safe
|
bool empty() const @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
typeof(this) save() @nogc nothrow pure @safe
|
typeof(this) save() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
@ -515,6 +481,7 @@ template isForwardRange(R)
|
|||||||
static struct Range2
|
static struct Range2
|
||||||
{
|
{
|
||||||
mixin InputRangeStub;
|
mixin InputRangeStub;
|
||||||
|
|
||||||
Range1 save() @nogc nothrow pure @safe
|
Range1 save() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return Range1();
|
return Range1();
|
||||||
@ -525,6 +492,7 @@ template isForwardRange(R)
|
|||||||
static struct Range3
|
static struct Range3
|
||||||
{
|
{
|
||||||
mixin InputRangeStub;
|
mixin InputRangeStub;
|
||||||
|
|
||||||
const(typeof(this)) save() const @nogc nothrow pure @safe
|
const(typeof(this)) save() const @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
@ -573,21 +541,26 @@ template isBidirectionalRange(R)
|
|||||||
void popFront() @nogc nothrow pure @safe
|
void popFront() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void popBack() @nogc nothrow pure @safe
|
void popBack() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@property int front() @nogc nothrow pure @safe
|
@property int front() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property int back() @nogc nothrow pure @safe
|
@property int back() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const @nogc nothrow pure @safe
|
bool empty() const @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Range save() @nogc nothrow pure @safe
|
Range save() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
@ -602,28 +575,17 @@ template isBidirectionalRange(R)
|
|||||||
{
|
{
|
||||||
static struct Range(T, U)
|
static struct Range(T, U)
|
||||||
{
|
{
|
||||||
void popFront() @nogc nothrow pure @safe
|
mixin BidirectionalRangeStub;
|
||||||
{
|
|
||||||
}
|
|
||||||
void popBack() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@property T front() @nogc nothrow pure @safe
|
@property T front() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return T.init;
|
return T.init;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property U back() @nogc nothrow pure @safe
|
@property U back() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return U.init;
|
return U.init;
|
||||||
}
|
}
|
||||||
bool empty() const @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Range save() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static assert(!isBidirectionalRange!(Range!(int, uint)));
|
static assert(!isBidirectionalRange!(Range!(int, uint)));
|
||||||
static assert(!isBidirectionalRange!(Range!(int, const int)));
|
static assert(!isBidirectionalRange!(Range!(int, const int)));
|
||||||
@ -674,29 +636,22 @@ template isRandomAccessRange(R)
|
|||||||
void popFront() @nogc nothrow pure @safe
|
void popFront() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void popBack() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@property int front() @nogc nothrow pure @safe
|
@property int front() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@property int back() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
bool empty() const @nogc nothrow pure @safe
|
bool empty() const @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
typeof(this) save() @nogc nothrow pure @safe
|
|
||||||
{
|
int opIndex(size_t) @nogc nothrow pure @safe
|
||||||
return this;
|
|
||||||
}
|
|
||||||
int opIndex(const size_t pos) @nogc nothrow pure @safe
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t length() const @nogc nothrow pure @safe
|
size_t length() const @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -711,15 +666,14 @@ template isRandomAccessRange(R)
|
|||||||
void popFront() @nogc nothrow pure @safe
|
void popFront() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@property int front() @nogc nothrow pure @safe
|
@property int front() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum bool empty = false;
|
enum bool empty = false;
|
||||||
typeof(this) save() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
int opIndex(const size_t pos) @nogc nothrow pure @safe
|
int opIndex(const size_t pos) @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -732,76 +686,43 @@ template isRandomAccessRange(R)
|
|||||||
{
|
{
|
||||||
static struct Range1
|
static struct Range1
|
||||||
{
|
{
|
||||||
mixin InputRangeStub;
|
|
||||||
mixin BidirectionalRangeStub;
|
mixin BidirectionalRangeStub;
|
||||||
|
mixin RandomAccessRangeStub;
|
||||||
typeof(this) save() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
int opIndex(const size_t pos) @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static assert(!isRandomAccessRange!Range1);
|
static assert(!isRandomAccessRange!Range1);
|
||||||
|
|
||||||
|
@Length
|
||||||
static struct Range2(Args...)
|
static struct Range2(Args...)
|
||||||
{
|
{
|
||||||
mixin InputRangeStub;
|
|
||||||
mixin BidirectionalRangeStub;
|
mixin BidirectionalRangeStub;
|
||||||
|
|
||||||
typeof(this) save() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
int opIndex(Args) @nogc nothrow pure @safe
|
int opIndex(Args) @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t length() const @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static assert(isRandomAccessRange!(Range2!size_t));
|
static assert(isRandomAccessRange!(Range2!size_t));
|
||||||
static assert(!isRandomAccessRange!(Range2!()));
|
static assert(!isRandomAccessRange!(Range2!()));
|
||||||
static assert(!isRandomAccessRange!(Range2!(size_t, size_t)));
|
static assert(!isRandomAccessRange!(Range2!(size_t, size_t)));
|
||||||
|
|
||||||
|
@Length
|
||||||
static struct Range3
|
static struct Range3
|
||||||
{
|
{
|
||||||
mixin InputRangeStub;
|
|
||||||
mixin BidirectionalRangeStub;
|
mixin BidirectionalRangeStub;
|
||||||
|
|
||||||
typeof(this) save() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
int opIndex(const size_t pos1, const size_t pos2 = 0)
|
int opIndex(const size_t pos1, const size_t pos2 = 0)
|
||||||
@nogc nothrow pure @safe
|
@nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t length() const @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static assert(isRandomAccessRange!Range3);
|
static assert(isRandomAccessRange!Range3);
|
||||||
|
|
||||||
static struct Range4
|
static struct Range4
|
||||||
{
|
{
|
||||||
mixin InputRangeStub;
|
|
||||||
mixin BidirectionalRangeStub;
|
mixin BidirectionalRangeStub;
|
||||||
|
mixin RandomAccessRangeStub;
|
||||||
|
|
||||||
typeof(this) save() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
int opIndex(const size_t pos1) @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t opDollar() const @nogc nothrow pure @safe
|
size_t opDollar() const @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -1097,28 +1018,20 @@ template isInfinite(R)
|
|||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
|
@Infinite
|
||||||
static struct StaticConstRange
|
static struct StaticConstRange
|
||||||
{
|
{
|
||||||
void popFront() @nogc nothrow pure @safe
|
mixin InputRangeStub;
|
||||||
{
|
|
||||||
}
|
|
||||||
@property int front() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static bool empty = false;
|
static bool empty = false;
|
||||||
}
|
}
|
||||||
static assert(!isInfinite!StaticConstRange);
|
static assert(!isInfinite!StaticConstRange);
|
||||||
|
|
||||||
|
@Infinite
|
||||||
static struct TrueRange
|
static struct TrueRange
|
||||||
{
|
{
|
||||||
void popFront() @nogc nothrow pure @safe
|
mixin InputRangeStub;
|
||||||
{
|
|
||||||
}
|
|
||||||
@property int front() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static const bool empty = true;
|
static const bool empty = true;
|
||||||
}
|
}
|
||||||
static assert(!isInfinite!TrueRange);
|
static assert(!isInfinite!TrueRange);
|
||||||
@ -1348,15 +1261,12 @@ if (isBidirectionalRange!R)
|
|||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
|
@Infinite
|
||||||
static struct InfiniteRange
|
static struct InfiniteRange
|
||||||
{
|
{
|
||||||
|
mixin ForwardRangeStub;
|
||||||
private int i;
|
private int i;
|
||||||
|
|
||||||
InfiniteRange save() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void popFront() @nogc nothrow pure @safe
|
void popFront() @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
++this.i;
|
++this.i;
|
||||||
@ -1376,8 +1286,6 @@ if (isBidirectionalRange!R)
|
|||||||
{
|
{
|
||||||
return this.i;
|
return this.i;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum bool empty = false;
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
InfiniteRange range;
|
InfiniteRange range;
|
||||||
@ -1497,44 +1405,19 @@ if (isInputRange!R)
|
|||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
static struct Element
|
|
||||||
{
|
|
||||||
this(this) @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns its elements by reference.
|
// Returns its elements by reference.
|
||||||
|
@Infinite @WithLvalueElements
|
||||||
static struct R1
|
static struct R1
|
||||||
{
|
{
|
||||||
Element element;
|
mixin InputRangeStub!AssertPostblit;
|
||||||
enum bool empty = false;
|
|
||||||
|
|
||||||
ref Element front() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
void popFront() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static assert(is(typeof(moveFront(R1()))));
|
static assert(is(typeof(moveFront(R1()))));
|
||||||
|
|
||||||
// Returns elements with a postblit constructor by value. moveFront fails.
|
// Returns elements with a postblit constructor by value. moveFront fails.
|
||||||
|
@Infinite
|
||||||
static struct R2
|
static struct R2
|
||||||
{
|
{
|
||||||
enum bool empty = false;
|
mixin InputRangeStub!AssertPostblit;
|
||||||
|
|
||||||
Element front() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return Element();
|
|
||||||
}
|
|
||||||
|
|
||||||
void popFront() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static assert(!is(typeof(moveFront(R2()))));
|
static assert(!is(typeof(moveFront(R2()))));
|
||||||
}
|
}
|
||||||
@ -1582,58 +1465,19 @@ if (isBidirectionalRange!R)
|
|||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
static struct Element
|
|
||||||
{
|
|
||||||
this(this) @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns its elements by reference.
|
// Returns its elements by reference.
|
||||||
|
@Infinite @WithLvalueElements
|
||||||
static struct R1
|
static struct R1
|
||||||
{
|
{
|
||||||
Element element;
|
mixin BidirectionalRangeStub!AssertPostblit;
|
||||||
enum bool empty = false;
|
|
||||||
|
|
||||||
ref Element back() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
alias front = back;
|
|
||||||
|
|
||||||
void popBack() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
}
|
|
||||||
alias popFront = popBack;
|
|
||||||
|
|
||||||
R1 save() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static assert(is(typeof(moveBack(R1()))));
|
static assert(is(typeof(moveBack(R1()))));
|
||||||
|
|
||||||
// Returns elements with a postblit constructor by value. moveBack fails.
|
// Returns elements with a postblit constructor by value. moveBack fails.
|
||||||
|
@Infinite
|
||||||
static struct R2
|
static struct R2
|
||||||
{
|
{
|
||||||
enum bool empty = false;
|
mixin BidirectionalRangeStub!AssertPostblit;
|
||||||
|
|
||||||
Element back() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return Element();
|
|
||||||
}
|
|
||||||
alias front = back;
|
|
||||||
|
|
||||||
void popBack() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
}
|
|
||||||
alias popFront = popBack;
|
|
||||||
|
|
||||||
R2 save() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static assert(!is(typeof(moveBack(R2()))));
|
static assert(!is(typeof(moveBack(R2()))));
|
||||||
}
|
}
|
||||||
@ -1680,54 +1524,19 @@ if (isRandomAccessRange!R)
|
|||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
static struct Element
|
|
||||||
{
|
|
||||||
this(this) @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns its elements by reference.
|
// Returns its elements by reference.
|
||||||
|
@Infinite @WithLvalueElements
|
||||||
static struct R1
|
static struct R1
|
||||||
{
|
{
|
||||||
Element element;
|
mixin RandomAccessRangeStub!AssertPostblit;
|
||||||
enum bool empty = false;
|
|
||||||
|
|
||||||
ref Element front() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
void popFront() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ref Element opIndex(size_t)
|
|
||||||
{
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static assert(is(typeof(moveAt(R1(), 0))));
|
static assert(is(typeof(moveAt(R1(), 0))));
|
||||||
|
|
||||||
// Returns elements with a postblit constructor by value. moveAt fails.
|
// Returns elements with a postblit constructor by value. moveAt fails.
|
||||||
|
@Infinite
|
||||||
static struct R2
|
static struct R2
|
||||||
{
|
{
|
||||||
enum bool empty = false;
|
mixin RandomAccessRangeStub!AssertPostblit;
|
||||||
|
|
||||||
Element front() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return Element();
|
|
||||||
}
|
|
||||||
|
|
||||||
void popFront() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Element opIndex() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return Element();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static assert(!is(typeof(moveAt(R2(), 0))));
|
static assert(!is(typeof(moveAt(R2(), 0))));
|
||||||
}
|
}
|
||||||
|
@ -15,3 +15,4 @@
|
|||||||
module tanya.test;
|
module tanya.test;
|
||||||
|
|
||||||
public import tanya.test.assertion;
|
public import tanya.test.assertion;
|
||||||
|
public import tanya.test.stub;
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
/* 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/. */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Range generators for tests.
|
|
||||||
|
|
||||||
* Copyright: Eugene Wissner 2018.
|
|
||||||
* 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/source/tanya/test/range.d,
|
|
||||||
* tanya/test/range.d)
|
|
||||||
*/
|
|
||||||
module tanya.test.range;
|
|
||||||
|
|
||||||
package(tanya) struct Empty
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
package(tanya) template InputRange()
|
|
||||||
{
|
|
||||||
import tanya.meta.metafunction : AliasSeq;
|
|
||||||
|
|
||||||
private alias attributes = AliasSeq!(__traits(getAttributes, typeof(this)));
|
|
||||||
|
|
||||||
static foreach (attribute; attributes)
|
|
||||||
{
|
|
||||||
static if (is(attribute == Empty))
|
|
||||||
{
|
|
||||||
@property bool empty() const @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void popFront() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
static foreach (attribute; attributes)
|
|
||||||
{
|
|
||||||
static if (is(attribute == Empty))
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int front() @nogc nothrow pure @safe
|
|
||||||
{
|
|
||||||
static foreach (attribute; attributes)
|
|
||||||
{
|
|
||||||
static if (is(attribute == Empty))
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
275
source/tanya/test/stub.d
Normal file
275
source/tanya/test/stub.d
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Range generators.
|
||||||
|
*
|
||||||
|
* Copyright: Eugene Wissner 2018.
|
||||||
|
* 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/source/tanya/test/stub.d,
|
||||||
|
* tanya/test/stub.d)
|
||||||
|
*/
|
||||||
|
module tanya.test.stub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute signalizing that the generated range should contain the given
|
||||||
|
* number of elements.
|
||||||
|
*
|
||||||
|
* $(D_PSYMBOL Count) should be always specified with some value and not as a
|
||||||
|
* type, so $(D_INLINECODE Count(1)) instead just $(D_INLINECODE Count),
|
||||||
|
* otherwise you can just omit $(D_PSYMBOL Count) and it will default to 0.
|
||||||
|
*
|
||||||
|
* $(D_PSYMBOL Count) doesn't generate `.length` property - use
|
||||||
|
* $(D_PSYMBOL Length) for that.
|
||||||
|
*
|
||||||
|
* If neither $(D_PSYMBOL Length) nor $(D_PSYMBOL Infinite) is given,
|
||||||
|
* $(D_ILNINECODE Count(0)) is assumed.
|
||||||
|
*
|
||||||
|
* This attribute conflicts with $(D_PSYMBOL Infinite) and $(D_PSYMBOL Length).
|
||||||
|
*/
|
||||||
|
struct Count
|
||||||
|
{
|
||||||
|
/// Original range length.
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
@disable this();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the attribute with the given length.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* count = Original range length.
|
||||||
|
*/
|
||||||
|
this(size_t count) @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute signalizing that the generated range should be infinite.
|
||||||
|
*
|
||||||
|
* This attribute conflicts with $(D_PSYMBOL Count) and $(D_PSYMBOL Length).
|
||||||
|
*/
|
||||||
|
struct Infinite
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates `.length` property for the range.
|
||||||
|
*
|
||||||
|
* The length of the range can be specified as a constructor argument,
|
||||||
|
* otherwise it is 0.
|
||||||
|
*
|
||||||
|
* This attribute conflicts with $(D_PSYMBOL Count) and $(D_PSYMBOL Infinite).
|
||||||
|
*/
|
||||||
|
struct Length
|
||||||
|
{
|
||||||
|
/// Original range length.
|
||||||
|
size_t length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute signalizing that the generated range should return values by
|
||||||
|
* reference.
|
||||||
|
*
|
||||||
|
* This atribute affects the return values of `.front`, `.back` and `[]`.
|
||||||
|
*/
|
||||||
|
struct WithLvalueElements
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an input range.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* E = Element type.
|
||||||
|
*/
|
||||||
|
mixin template InputRangeStub(E = int)
|
||||||
|
{
|
||||||
|
import tanya.meta.metafunction : Alias;
|
||||||
|
import tanya.meta.trait : getUDAs, hasUDA;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Aliases for the attribute lookups to access them faster
|
||||||
|
*/
|
||||||
|
private enum bool infinite = hasUDA!(typeof(this), Infinite);
|
||||||
|
private enum bool withLvalueElements = hasUDA!(typeof(this),
|
||||||
|
WithLvalueElements);
|
||||||
|
private alias Count = getUDAs!(typeof(this), .Count);
|
||||||
|
private alias Length = getUDAs!(typeof(this), .Length);
|
||||||
|
|
||||||
|
static if (Count.length != 0)
|
||||||
|
{
|
||||||
|
private enum size_t count = Count[0].count;
|
||||||
|
|
||||||
|
static assert (!infinite,
|
||||||
|
"Range cannot have count and be infinite at the same time");
|
||||||
|
static assert (Length.length == 0,
|
||||||
|
"Range cannot have count and length at the same time");
|
||||||
|
}
|
||||||
|
else static if (Length.length != 0)
|
||||||
|
{
|
||||||
|
private enum size_t count = evalUDA!(Length[0]).length;
|
||||||
|
|
||||||
|
static assert (!infinite,
|
||||||
|
"Range cannot have length and be infinite at the same time");
|
||||||
|
}
|
||||||
|
else static if (!infinite)
|
||||||
|
{
|
||||||
|
private enum size_t count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Member generation
|
||||||
|
*/
|
||||||
|
static if (infinite)
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
private size_t length_ = count;
|
||||||
|
|
||||||
|
@property bool empty() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this.length_ == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (withLvalueElements)
|
||||||
|
{
|
||||||
|
private E* element; // Pointer to enable range copying in save()
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
in (!empty)
|
||||||
|
{
|
||||||
|
static if (!infinite)
|
||||||
|
{
|
||||||
|
--this.length_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (withLvalueElements)
|
||||||
|
{
|
||||||
|
ref E front() @nogc nothrow pure @safe
|
||||||
|
in (!empty)
|
||||||
|
{
|
||||||
|
return *this.element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
E front() @nogc nothrow pure @safe
|
||||||
|
in (!empty)
|
||||||
|
{
|
||||||
|
return E.init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (Length.length != 0)
|
||||||
|
{
|
||||||
|
size_t length() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this.length_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a forward range.
|
||||||
|
*
|
||||||
|
* This mixin includes input range primitives as well, but can be combined with
|
||||||
|
* $(D_PSYMBOL RandomAccessRangeStub).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* E = Element type.
|
||||||
|
*/
|
||||||
|
mixin template ForwardRangeStub(E = int)
|
||||||
|
{
|
||||||
|
static if (!is(typeof(this.InputRangeMixin) == void))
|
||||||
|
{
|
||||||
|
mixin InputRangeStub!E InputRangeMixin;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto save() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a bidirectional range.
|
||||||
|
*
|
||||||
|
* This mixin includes forward range primitives as well, but can be combined with
|
||||||
|
* $(D_PSYMBOL RandomAccessRangeStub).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* E = Element type.
|
||||||
|
*/
|
||||||
|
mixin template BidirectionalRangeStub(E = int)
|
||||||
|
{
|
||||||
|
mixin ForwardRangeStub!E;
|
||||||
|
|
||||||
|
void popBack() @nogc nothrow pure @safe
|
||||||
|
in (!empty)
|
||||||
|
{
|
||||||
|
static if (!infinite)
|
||||||
|
{
|
||||||
|
--this.length_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (withLvalueElements)
|
||||||
|
{
|
||||||
|
ref E back() @nogc nothrow pure @safe
|
||||||
|
in (!empty)
|
||||||
|
{
|
||||||
|
return *this.element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
E back() @nogc nothrow pure @safe
|
||||||
|
in (!empty)
|
||||||
|
{
|
||||||
|
return E.init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a random-access range.
|
||||||
|
*
|
||||||
|
* This mixin includes input range primitives as well, but can be combined with
|
||||||
|
* $(D_PSYMBOL ForwardRangeStub) or $(D_PSYMBOL BidirectionalRangeStub).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* E = Element type.
|
||||||
|
*/
|
||||||
|
mixin template RandomAccessRangeStub(E = int)
|
||||||
|
{
|
||||||
|
static if (!is(typeof(this.InputRangeMixin) == void))
|
||||||
|
{
|
||||||
|
mixin InputRangeStub!E InputRangeMixin;
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (withLvalueElements)
|
||||||
|
{
|
||||||
|
ref E opIndex(size_t) @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return *this.element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
E opIndex(size_t) @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return E.init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user