auto concat(T : E[n], E, size_t n)(const E[][] args...) @nogc
{
    size_t offset = 0;
    T result = void;
    foreach(arr; args) {
        result[offset .. offset+arr.length] = arr;
        offset += arr.length;
    }
    assert(offset == result.length);
    return result;
}

static immutable ubyte[4] sigma0 = [101, 120, 112,  97];
static immutable ubyte[4] sigma1 = [110, 100,  32,  51];
static immutable ubyte[4] sigma2 = [ 50,  45,  98, 121];
static immutable ubyte[4] sigma3 = [116, 101,  32, 107];

void func(in ref ubyte[32] key, in ref ubyte[16] n) @nogc
{
    ubyte[64] buf;
    buf[0..4] = sigma0;
    buf[4..20] = key[0..16];
    buf[20..24] = sigma1;
    buf[24..40] = n;
    buf[40..44] = sigma2;
    buf[44..60] = key[16..$];
    buf[60..64] = sigma3;

auto buf2 = concat!(ubyte[64])(sigma0, key[0..16], sigma1, n, sigma2, key[16..$], sigma3);

    assert(buf == buf2);
}

void main() {
ubyte[32] key = [0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1];
    ubyte[16] n   = key[0..16];
    func(key, n);
}


Some remarks:

* I added `ref` to `func`'s parameters, because the arrays are relatively large, so passing them by value might be costly (you should measure it if you care).

* The `void` initialization in `concat` is an optimization that is valid only for POD types.

* Returning the array is cheap because of NRVO.

Reply via email to