module cm3d2.util; import std.bitmanip; import std.range; import std.traits; ubyte readByte(Range)(ref Range data) if (isRandomAccessRange!(Unqual!(Range)) && is(ElementType!Range == ubyte) && hasSlicing!Range) { auto value = data[0]; data = data[1 .. $]; return value; } ubyte[] readBytes(Range)(ref Range data, uint count) if (isRandomAccessRange!(Unqual!(Range)) && is(ElementType!Range == ubyte) && hasSlicing!Range) { ubyte[] bytes = new ubyte[count]; for (auto i = 0; i < count; i++) { bytes[i] = data.readByte(); } return bytes; } string readString(Range)(ref Range data) if (isRandomAccessRange!(Unqual!(Range)) && is(ElementType!Range == ubyte) && hasSlicing!Range) { auto length = 0; ubyte[] chars; while (true) { auto lengthByte = data.readByte(); if (length != 0 && lengthByte < 128) { break; } length = length << 8 | lengthByte; if (lengthByte < 128) { break; } } auto value = cast(string) data[0 .. length]; data = data[length .. $]; return value; } uint readInt(Range)(ref Range data) if (isRandomAccessRange!(Unqual!(Range)) && is(ElementType!Range == ubyte) && hasSlicing!Range) { auto value = littleEndianToNative!uint(data[0 .. 4]); data = data[4 .. $]; return value; }