Use standard range API

This commit is contained in:
2025-08-27 13:52:11 +02:00
parent b8fa670c5a
commit 2a67ccd954
23 changed files with 21 additions and 1763 deletions

View File

@@ -19,7 +19,6 @@ programming in D.
Tanya consists of the following packages and (top-level) modules: Tanya consists of the following packages and (top-level) modules:
* `algorithm`: Collection of generic algorithms. * `algorithm`: Collection of generic algorithms.
* `bitmanip`: Bit manipulation.
* `container`: Queue, Array, Singly and doubly linked lists, Buffers, UTF-8 * `container`: Queue, Array, Singly and doubly linked lists, Buffers, UTF-8
string, Set, Hash table. string, Set, Hash table.
* `conv`: This module provides functions for converting between different * `conv`: This module provides functions for converting between different
@@ -36,8 +35,6 @@ arguments.
* `os`: Platform-independent interfaces to operating system functionality. * `os`: Platform-independent interfaces to operating system functionality.
* `range`: Generic functions and templates for D ranges. * `range`: Generic functions and templates for D ranges.
* `test`: Test suite for unittest-blocks. * `test`: Test suite for unittest-blocks.
* `typecons`: Templates that allow to build new types based on the available
ones.
## NogcD ## NogcD

View File

@@ -20,6 +20,7 @@
*/ */
module tanya.algorithm.iteration; module tanya.algorithm.iteration;
import std.range : isBidirectionalRange;
import std.traits; import std.traits;
import std.typecons; import std.typecons;
import tanya.memory.lifetime; import tanya.memory.lifetime;

View File

@@ -14,6 +14,7 @@
*/ */
module tanya.algorithm.mutation; module tanya.algorithm.mutation;
import std.range : hasLvalueElements, isInputRange, isOutputRange, put;
import std.traits; import std.traits;
static import tanya.memory.lifetime; static import tanya.memory.lifetime;
static import tanya.memory.op; static import tanya.memory.op;

View File

@@ -18,6 +18,7 @@ import core.checkedint;
import std.algorithm.comparison; import std.algorithm.comparison;
import std.algorithm.iteration; import std.algorithm.iteration;
import std.algorithm.mutation : bringToFront; import std.algorithm.mutation : bringToFront;
import std.range : isInfinite, isInputRange;
import std.traits; import std.traits;
import tanya.algorithm.mutation; import tanya.algorithm.mutation;
import tanya.memory.allocator; import tanya.memory.allocator;

View File

@@ -15,6 +15,7 @@
module tanya.container.hashtable; module tanya.container.hashtable;
import std.algorithm.iteration; import std.algorithm.iteration;
import std.range : isInfinite, isForwardRange;
import std.traits; import std.traits;
import tanya.algorithm.mutation; import tanya.algorithm.mutation;
import tanya.container.array; import tanya.container.array;

View File

@@ -17,6 +17,7 @@ module tanya.container.list;
import std.algorithm.comparison; import std.algorithm.comparison;
import std.algorithm.iteration; import std.algorithm.iteration;
import std.range : isInfinite, isInputRange;
import std.traits; import std.traits;
import tanya.container.entry; import tanya.container.entry;
import tanya.memory.allocator; import tanya.memory.allocator;

View File

@@ -15,6 +15,7 @@
*/ */
module tanya.container.set; module tanya.container.set;
import std.range : isInfinite, isForwardRange;
import std.traits; import std.traits;
import tanya.container.array; import tanya.container.array;
import tanya.container.entry; import tanya.container.entry;

View File

@@ -28,6 +28,7 @@ module tanya.container.string;
import std.algorithm.comparison; import std.algorithm.comparison;
import std.algorithm.mutation : bringToFront; import std.algorithm.mutation : bringToFront;
import std.range : isInfinite, popFrontN, isInputRange;
import std.traits; import std.traits;
import tanya.algorithm.mutation; import tanya.algorithm.mutation;
import tanya.hash.lookup; import tanya.hash.lookup;

View File

@@ -14,6 +14,7 @@
*/ */
module tanya.conv; module tanya.conv;
import std.range : isInputRange;
import std.traits; import std.traits;
import tanya.container.string; import tanya.container.string;
import tanya.memory.allocator; import tanya.memory.allocator;

View File

@@ -51,6 +51,7 @@ import std.algorithm.comparison;
import std.ascii; import std.ascii;
import std.math : signbit; import std.math : signbit;
import std.meta; import std.meta;
import std.range : isInfinite, popFrontExactly, isInputRange, isOutputRange, put;
import std.traits; import std.traits;
import tanya.container.string; import tanya.container.string;
import tanya.math; import tanya.math;

View File

@@ -14,6 +14,7 @@
*/ */
module tanya.hash.lookup; module tanya.hash.lookup;
import std.range : isInfinite, isInputRange;
import std.traits; import std.traits;
import tanya.meta; import tanya.meta;
import tanya.range.primitive; import tanya.range.primitive;

View File

@@ -14,6 +14,7 @@
*/ */
module tanya.net.iface; module tanya.net.iface;
import std.range : isInputRange;
import std.traits; import std.traits;
import tanya.algorithm.mutation; import tanya.algorithm.mutation;
import tanya.container.string; import tanya.container.string;

View File

@@ -14,6 +14,7 @@
*/ */
module tanya.net.inet; module tanya.net.inet;
import std.range : isInfinite, isInputRange;
import std.traits; import std.traits;
import tanya.meta; import tanya.meta;
import tanya.range; import tanya.range;

View File

@@ -16,6 +16,7 @@ module tanya.net.ip;
import std.algorithm.comparison; import std.algorithm.comparison;
import std.ascii; import std.ascii;
import std.range : isForwardRange, isInputRange, isOutputRange, put;
import std.sumtype; import std.sumtype;
import std.typecons; import std.typecons;
import std.traits; import std.traits;

View File

@@ -14,6 +14,7 @@
*/ */
module tanya.range.adapter; module tanya.range.adapter;
import std.range : isInputRange, isOutputRange, put;
import std.traits; import std.traits;
import tanya.algorithm.mutation; import tanya.algorithm.mutation;
import tanya.memory.lifetime; import tanya.memory.lifetime;

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,7 @@
module tanya.algorithm.tests.iteration; module tanya.algorithm.tests.iteration;
import std.range : isBidirectionalRange, isRandomAccessRange;
import tanya.algorithm.iteration; import tanya.algorithm.iteration;
import tanya.range; import tanya.range;
import tanya.test.stub; import tanya.test.stub;

View File

@@ -8,7 +8,8 @@ import tanya.test.stub;
@nogc nothrow pure @safe unittest @nogc nothrow pure @safe unittest
{ {
import tanya.range.primitive : isForwardRange; import std.range : isForwardRange;
static assert(is(HashTable!(string, int) a)); static assert(is(HashTable!(string, int) a));
static assert(is(const HashTable!(string, int))); static assert(is(const HashTable!(string, int)));
static assert(isForwardRange!(HashTable!(string, int).Range)); static assert(isForwardRange!(HashTable!(string, int).Range));

View File

@@ -41,14 +41,6 @@ import tanya.test.stub;
// Static checks. // Static checks.
@nogc nothrow pure @safe unittest @nogc nothrow pure @safe unittest
{ {
import tanya.range.primitive;
static assert(isBidirectionalRange!(Set!int.ConstRange));
static assert(isBidirectionalRange!(Set!int.Range));
static assert(!isInfinite!(Set!int.Range));
static assert(!hasLength!(Set!int.Range));
static assert(is(Set!uint)); static assert(is(Set!uint));
static assert(is(Set!long)); static assert(is(Set!long));
static assert(is(Set!ulong)); static assert(is(Set!ulong));

View File

@@ -4,7 +4,7 @@
module tanya.net.tests.inet; module tanya.net.tests.inet;
import tanya.net.inet; import tanya.net.inet;
import tanya.range; import std.range;
// Static tests // Static tests
@nogc nothrow pure @safe unittest @nogc nothrow pure @safe unittest

View File

@@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
module tanya.range.tests.adapter; module tanya.range.tests.adapter;
import std.range : isOutputRange;
import tanya.range; import tanya.range;
private struct Container private struct Container

View File

@@ -1,387 +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/. */
module tanya.range.tests.primitive;
import tanya.range;
import tanya.test.stub;
private struct AssertPostblit
{
this(this) @nogc nothrow pure @safe
{
assert(false);
}
}
@nogc nothrow pure @safe unittest
{
static struct Range1(T)
{
mixin InputRangeStub;
T empty() const
{
return true;
}
}
static assert(!isInputRange!(Range1!int));
static assert(!isInputRange!(Range1!(const bool)));
static struct Range2
{
mixin InputRangeStub;
int popFront() @nogc nothrow pure @safe
{
return 100;
}
}
static assert(isInputRange!Range2);
static struct Range3
{
mixin InputRangeStub;
void front() @nogc nothrow pure @safe
{
}
}
static assert(!isInputRange!Range3);
static struct Range4
{
mixin InputRangeStub;
enum bool empty = false;
}
static assert(isInputRange!Range4);
}
// Ranges with non-copyable elements can be input ranges
@nogc nothrow pure @safe unittest
{
@WithLvalueElements
static struct R
{
mixin InputRangeStub!NonCopyable;
}
static assert(isInputRange!R);
}
// Ranges with const non-copyable elements can be input ranges
@nogc nothrow pure @safe unittest
{
@WithLvalueElements
static struct R
{
mixin InputRangeStub!(const(NonCopyable));
}
static assert(isInputRange!R);
}
@nogc nothrow pure @safe unittest
{
static struct Range1
{
}
static struct Range2
{
mixin InputRangeStub;
Range1 save() @nogc nothrow pure @safe
{
return Range1();
}
}
static assert(!isForwardRange!Range2);
static struct Range3
{
mixin InputRangeStub;
const(typeof(this)) save() const @nogc nothrow pure @safe
{
return this;
}
}
static assert(!isForwardRange!Range3);
}
@nogc nothrow pure @safe unittest
{
static struct Range(T, U)
{
mixin BidirectionalRangeStub;
@property T front() @nogc nothrow pure @safe
{
return T.init;
}
@property U back() @nogc nothrow pure @safe
{
return U.init;
}
}
static assert(!isBidirectionalRange!(Range!(int, uint)));
static assert(!isBidirectionalRange!(Range!(int, const int)));
}
// Ranges with non-copyable elements can be bidirectional ranges
@nogc nothrow pure @safe unittest
{
@WithLvalueElements
static struct R
{
mixin BidirectionalRangeStub!NonCopyable;
}
static assert(isBidirectionalRange!R);
}
@nogc nothrow pure @safe unittest
{
static struct Range1
{
mixin BidirectionalRangeStub;
mixin RandomAccessRangeStub;
}
static assert(!isRandomAccessRange!Range1);
@Length
static struct Range2(Args...)
{
mixin BidirectionalRangeStub;
int opIndex(Args) @nogc nothrow pure @safe
{
return 0;
}
}
static assert(isRandomAccessRange!(Range2!size_t));
static assert(!isRandomAccessRange!(Range2!()));
static assert(!isRandomAccessRange!(Range2!(size_t, size_t)));
@Length
static struct Range3
{
mixin BidirectionalRangeStub;
int opIndex(const size_t pos1, const size_t pos2 = 0)
@nogc nothrow pure @safe
{
return 0;
}
}
static assert(isRandomAccessRange!Range3);
static struct Range4
{
mixin BidirectionalRangeStub;
mixin RandomAccessRangeStub;
size_t opDollar() const @nogc nothrow pure @safe
{
return 0;
}
}
static assert(!isRandomAccessRange!Range4);
}
// Ranges with non-copyable elements can be random-access ranges
@nogc nothrow pure @safe unittest
{
@WithLvalueElements @Infinite
static struct R
{
mixin RandomAccessRangeStub!NonCopyable;
}
static assert(isRandomAccessRange!R);
}
@nogc nothrow pure @safe unittest
{
@Infinite
static struct StaticConstRange
{
mixin InputRangeStub;
static bool empty = false;
}
static assert(!isInfinite!StaticConstRange);
@Infinite
static struct TrueRange
{
mixin InputRangeStub;
static const bool empty = true;
}
static assert(!isInfinite!TrueRange);
}
@nogc nothrow pure @safe unittest
{
@Infinite
static struct InfiniteRange
{
mixin ForwardRangeStub;
private int i;
void popFront() @nogc nothrow pure @safe
{
++this.i;
}
void popBack() @nogc nothrow pure @safe
{
--this.i;
}
@property int front() const @nogc nothrow pure @safe
{
return this.i;
}
@property int back() const @nogc nothrow pure @safe
{
return this.i;
}
}
{
InfiniteRange range;
popFrontExactly(range, 2);
assert(range.front == 2);
popFrontN(range, 2);
assert(range.front == 4);
}
{
InfiniteRange range;
popBackExactly(range, 2);
assert(range.back == -2);
popBackN(range, 2);
assert(range.back == -4);
}
}
@nogc nothrow pure @safe unittest
{
static struct Range
{
private int[5] a = [1, 2, 3, 4, 5];
private size_t begin = 0, end = 5;
Range save() @nogc nothrow pure @safe
{
return this;
}
void popFront() @nogc nothrow pure @safe
{
++this.begin;
}
void popBack() @nogc nothrow pure @safe
{
--this.end;
}
@property int front() const @nogc nothrow pure @safe
{
return this.a[this.begin];
}
@property int back() const @nogc nothrow pure @safe
{
return this.a[this.end - 1];
}
@property bool empty() const @nogc nothrow pure @safe
{
return this.begin >= this.end;
}
}
{
Range range;
popFrontN(range, 3);
assert(range.front == 4);
assert(range.back == 5);
popFrontN(range, 20);
assert(range.empty);
}
{
Range range;
popBackN(range, 3);
assert(range.front == 1);
assert(range.back == 2);
popBackN(range, 20);
assert(range.empty);
}
}
@nogc nothrow pure @safe unittest
{
// Returns its elements by reference.
@Infinite @WithLvalueElements
static struct R1
{
mixin InputRangeStub!AssertPostblit;
}
static assert(is(typeof(moveFront(R1()))));
// Returns elements with a postblit constructor by value. moveFront fails.
@Infinite
static struct R2
{
mixin InputRangeStub!AssertPostblit;
}
static assert(!is(typeof(moveFront(R2()))));
}
@nogc nothrow pure @safe unittest
{
// Returns its elements by reference.
@Infinite @WithLvalueElements
static struct R1
{
mixin BidirectionalRangeStub!AssertPostblit;
}
static assert(is(typeof(moveBack(R1()))));
// Returns elements with a postblit constructor by value. moveBack fails.
@Infinite
static struct R2
{
mixin BidirectionalRangeStub!AssertPostblit;
}
static assert(!is(typeof(moveBack(R2()))));
}
@nogc nothrow pure @safe unittest
{
// Returns its elements by reference.
@Infinite @WithLvalueElements
static struct R1
{
mixin RandomAccessRangeStub!AssertPostblit;
}
static assert(is(typeof(moveAt(R1(), 0))));
// Returns elements with a postblit constructor by value. moveAt fails.
@Infinite
static struct R2
{
mixin RandomAccessRangeStub!AssertPostblit;
}
static assert(!is(typeof(moveAt(R2(), 0))));
}
// Works with non-copyable elements
@nogc nothrow pure @safe unittest
{
static assert(hasLvalueElements!(NonCopyable[]));
}

View File

@@ -1,5 +1,6 @@
module tanya.tests.format; module tanya.tests.format;
import std.range : put;
import tanya.format; import tanya.format;
import tanya.range; import tanya.range;