range.adapter: new arrayInserter

This commit is contained in:
Eugen Wissner 2019-02-24 13:10:45 +01:00
parent 87ba58098e
commit df99ea45f2
1 changed files with 70 additions and 1 deletions

View File

@ -14,6 +14,7 @@
*/
module tanya.range.adapter;
import tanya.algorithm.mutation;
import tanya.functional;
import tanya.meta.trait;
import tanya.range;
@ -32,7 +33,7 @@ private mixin template InserterCtor()
{
private Container* container;
this(ref Container container) @trusted
private this(ref Container container) @trusted
{
this.container = &container;
}
@ -159,3 +160,71 @@ if (hasMember!(Container, "insertFront"))
assert(container.element == 5);
}
/**
* $(D_PSYMBOL arrayInserter) makes an output range out of an array.
*
* The returned output range accepts single values as well as input ranges that
* can be copied into the target array.
*
* Params:
* Array = Array type.
* array = Array.
*
* Returns: An output range writing into $(D_PARAM array).
*/
auto arrayInserter(Array)(return scope ref Array array)
if (isArray!Array)
{
static if (is(Array ArrayT : ArrayT[size], size_t size))
{
alias E = ArrayT;
}
else
{
alias E = ElementType!Array;
}
static struct ArrayInserter
{
private E[] data;
private this(ref Array data) @trusted
{
this.data = data[];
}
void opCall(T)(auto ref T data)
if (is(T : E))
in (!this.data.empty)
{
put(this.data, data);
}
void opCall(R)(auto ref R data)
if (isInputRange!R && isOutputRange!(E[], ElementType!R))
{
this.data = copy(data, this.data);
}
}
return ArrayInserter(array);
}
///
@nogc nothrow pure @safe unittest
{
int[1] array;
arrayInserter(array)(5);
assert(array[0] == 5);
}
///
@nogc nothrow pure @safe unittest
{
char[1] array;
alias Actual = typeof(arrayInserter(array));
static assert(isOutputRange!(Actual, char));
static assert(isOutputRange!(Actual, char[]));
}