Fixed some endianess stuff and added bufferedChunks function

This commit is contained in:
Johannes Loher 2016-09-24 15:37:40 +02:00
parent f09a006b27
commit 62ccd373ab
4 changed files with 203 additions and 45 deletions

View file

@ -2,7 +2,7 @@ module bitmanip;
private import std.traits : isUnsigned;
private import std.bitmanip : nativeToLittleEndian, littleEndianToNative, nativeToBigEndian, bigEndianToNative;
private import std.bitmanip : nativeToLittleEndian, littleEndianToNative;
UIntType rotateLeft(UIntType)(in UIntType val, in size_t len) nothrow @nogc pure @safe
if (isUnsigned!UIntType)
@ -48,26 +48,3 @@ body
ubyte[uint.sizeof] buf = input;
return littleEndianToNative!uint(buf);
}
alias bigEndianInv = nativeToBigEndian;
uint bigEndian(in ubyte[] input) @safe pure nothrow @nogc
in
{
assert(input.length == uint.sizeof);
}
body
{
ubyte[uint.sizeof] buf = input;
return bigEndianToNative!uint(buf);
}
unittest
{
ubyte[] test0 = [0, 0, 0, 0];
ubyte[] test1 = [86, 75, 30, 9];
ubyte[] test2 = [255, 255, 255, 250];
assert(littleEndian(test0) == 0x00000000);
assert(littleEndian(test1) == 0x091e4b56);
assert(littleEndian(test2) == 0xfaffffff);
}

View file

@ -40,7 +40,8 @@ auto chacha20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce)
assert(!empty);
if (++chachaCounter == 64)
{
chachaSection = chacha20Exp(key, concat!(ubyte[16])(bigEndianInv(++count), nonce));
chachaSection = chacha20Exp(key,
concat!(ubyte[16])(littleEndianInv(++count), nonce));
chachaCounter = 0;
}
range.popFront();

View file

@ -41,7 +41,7 @@ auto salsa20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce)
if (++salsaCounter == 64)
{
salsaSection = salsa20Exp(key, concat!(ubyte[16])(nonce,
bigEndianInv(++count)));
littleEndianInv(++count)));
salsaCounter = 0;
}
range.popFront();
@ -81,9 +81,9 @@ enum string quarterRound(alias _x0, alias _x1, alias _x2, alias _x3) = q{
%2$s ^= (%1$s + %4$s).rotateLeft(7);
%3$s ^= (%2$s + %1$s).rotateLeft(9);
%4$s ^= (%3$s + %2$s).rotateLeft(13);
%1$s ^= (%4$s + %3$s).rotateLeft(18);
}.format(__traits(identifier, _x0),
__traits(identifier, _x1), __traits(identifier, _x2), __traits(identifier, _x3));
%1$s ^= (%4$s + %3$s).rotateLeft(18);}
.format(__traits(identifier, _x0),
__traits(identifier, _x1), __traits(identifier, _x2), __traits(identifier, _x3));
@safe unittest
{
@ -117,14 +117,13 @@ enum string rowRound(alias _x00, alias _x01, alias _x02, alias _x03, alias _x04,
mixin(quarterRound!(%1$s, %2$s, %3$s, %4$s));
mixin(quarterRound!(%6$s, %7$s, %8$s, %5$s));
mixin(quarterRound!(%11$s, %12$s, %9$s, %10$s));
mixin(quarterRound!(%16$s, %13$s, %14$s, %15$s));
}.format(
__traits(identifier, _x00), __traits(identifier,
_x01), __traits(identifier, _x02), __traits(identifier, _x03),
__traits(identifier, _x04), __traits(identifier, _x05), __traits(identifier, _x06),
__traits(identifier, _x07), __traits(identifier, _x08), __traits(identifier, _x09),
__traits(identifier, _x10), __traits(identifier, _x11), __traits(identifier, _x12),
__traits(identifier, _x13), __traits(identifier, _x14), __traits(identifier, _x15));
mixin(quarterRound!(%16$s, %13$s, %14$s, %15$s));}
.format(__traits(identifier, _x00), __traits(identifier, _x01),
__traits(identifier, _x02), __traits(identifier, _x03), __traits(identifier, _x04),
__traits(identifier, _x05), __traits(identifier, _x06), __traits(identifier, _x07),
__traits(identifier, _x08), __traits(identifier, _x09), __traits(identifier, _x10),
__traits(identifier, _x11), __traits(identifier, _x12), __traits(identifier,
_x13), __traits(identifier, _x14), __traits(identifier, _x15));
@safe unittest
{
@ -167,14 +166,13 @@ enum string colRound(alias _x00, alias _x01, alias _x02, alias _x03, alias _x04,
mixin(quarterRound!(%1$s, %5$s, %9$s, %13$s));
mixin(quarterRound!(%6$s, %10$s, %14$s, %2$s));
mixin(quarterRound!(%11$s, %15$s, %3$s, %7$s));
mixin(quarterRound!(%16$s, %4$s, %8$s, %12$s));
}.format(
__traits(identifier, _x00), __traits(identifier,
_x01), __traits(identifier, _x02), __traits(identifier, _x03),
__traits(identifier, _x04), __traits(identifier, _x05), __traits(identifier, _x06),
__traits(identifier, _x07), __traits(identifier, _x08), __traits(identifier, _x09),
__traits(identifier, _x10), __traits(identifier, _x11), __traits(identifier, _x12),
__traits(identifier, _x13), __traits(identifier, _x14), __traits(identifier, _x15));
mixin(quarterRound!(%16$s, %4$s, %8$s, %12$s));}
.format(__traits(identifier, _x00), __traits(identifier, _x01),
__traits(identifier, _x02), __traits(identifier, _x03), __traits(identifier, _x04),
__traits(identifier, _x05), __traits(identifier, _x06), __traits(identifier, _x07),
__traits(identifier, _x08), __traits(identifier, _x09), __traits(identifier, _x10),
__traits(identifier, _x11), __traits(identifier, _x12), __traits(identifier,
_x13), __traits(identifier, _x14), __traits(identifier, _x15));
@safe unittest
{

View file

@ -1,5 +1,8 @@
module utility;
private import std.range : isInputRange, isInfinite, isForwardRange,
ElementType;
auto concat(T : E[n], E, size_t n)(in E[][] args...) @nogc
{
size_t offset = 0;
@ -26,3 +29,182 @@ auto concat(T : E[n], E, size_t n)(in E[][] args...) @nogc
assert(concat!(int[6])([1], [2, 3], [4, 5, 6]) == [1, 2, 3, 4, 5, 6]);
assert(concat!(char[12])("Hello", " ", "World!") == "Hello World!");
}
auto bufferedChunks(Source)(Source source, size_t chunkSize)
if (isInputRange!Source)
{
static struct BufferedChunks
{
this(Source source, size_t chunkSize)
{
assert(chunkSize != 0, "Cannot create a Chunk with an empty chunkSize");
this.source = source;
this.chunkSize = chunkSize;
buffer.length = chunkSize;
foreach (i; 0 .. chunkSize)
{
if (!this.source.empty)
{
buffer[i] = this.source.front;
this.source.popFront;
bufferLength++;
}
else
break;
}
}
auto front() @property
{
assert(!empty);
return buffer[0 .. bufferLength];
}
void popFront()
{
assert(!empty);
bufferLength = 0;
if (!source.empty)
{
foreach (i; 0 .. chunkSize)
{
if (!source.empty)
{
buffer[i] = source.front;
source.popFront;
bufferLength++;
}
else
break;
}
}
}
static if (isInfinite!Source)
{
enum empty = false;
}
else
{
bool empty() @property
{
return bufferLength == 0;
}
}
static if (isForwardRange!Source)
{
auto save()
{
auto ret = this;
ret.source = source.save;
ret.buffer = buffer.dup;
return ret;
}
}
private:
Source source;
size_t chunkSize;
ElementType!Source[] buffer;
size_t bufferLength;
}
return BufferedChunks(source, chunkSize);
}
version (unittest) private import std.array;
@safe unittest
{
int[] testArray;
auto _bufferedChunks = bufferedChunks(testArray, 1);
assert(_bufferedChunks.empty);
}
@safe unittest
{
int[] testArray;
auto _bufferedChunks = bufferedChunks(testArray, 2);
assert(_bufferedChunks.empty);
}
@safe unittest
{
auto _bufferedChunks = bufferedChunks([0], 1);
assert(_bufferedChunks.front == [0]);
_bufferedChunks.popFront;
assert(_bufferedChunks.empty);
}
@safe unittest
{
auto _bufferedChunks = bufferedChunks([0], 2);
assert(_bufferedChunks.front == [0]);
_bufferedChunks.popFront;
assert(_bufferedChunks.empty);
}
@safe unittest
{
auto _bufferedChunks = bufferedChunks([0, 1], 1);
assert(_bufferedChunks.front == [0]);
_bufferedChunks.popFront;
assert(_bufferedChunks.front == [1]);
_bufferedChunks.popFront;
assert(_bufferedChunks.empty);
}
@safe unittest
{
auto _bufferedChunks = bufferedChunks([0, 1], 2);
assert(_bufferedChunks.front == [0, 1]);
_bufferedChunks.popFront;
assert(_bufferedChunks.empty);
}
@safe unittest
{
auto _bufferedChunks = bufferedChunks([0, 1, 2], 2);
assert(_bufferedChunks.front == [0, 1]);
_bufferedChunks.popFront;
assert(_bufferedChunks.front == [2]);
_bufferedChunks.popFront;
assert(_bufferedChunks.empty);
}
@safe unittest
{
auto _bufferedChunks = bufferedChunks([0, 1, 2, 3], 2);
assert(_bufferedChunks.front == [0, 1]);
_bufferedChunks.popFront;
assert(_bufferedChunks.front == [2, 3]);
_bufferedChunks.popFront;
assert(_bufferedChunks.empty);
}
@system unittest
{
import std.exception : assertThrown;
import core.exception : AssertError;
assertThrown!AssertError(bufferedChunks([0], 0));
}
@safe unittest
{
auto _bufferedChunks = bufferedChunks([0], 1);
auto otherBufferedChunks = _bufferedChunks.save;
_bufferedChunks.popFront;
assert(_bufferedChunks.empty);
assert(otherBufferedChunks.front == [0]);
}
@safe unittest
{
auto _bufferedChunks = bufferedChunks([0, 1], 1);
auto otherBufferedChunks = _bufferedChunks.save;
_bufferedChunks.popFront;
assert(_bufferedChunks.front == [1]);
assert(otherBufferedChunks.front == [0]);
}