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; } Range readBytes(Range)(ref Range data, size_t count) if (isRandomAccessRange!(Unqual!Range) && is(ElementType!Range == ubyte) && hasSlicing!Range) { auto bytes = data[0 .. count]; data = data[count .. $]; 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; } Integer readInteger(Integer, Range)(ref Range data) if (isRandomAccessRange!(Unqual!Range) && is(ElementType!Range == ubyte) && hasSlicing!Range) { auto value = littleEndianToNative!Integer(data[0 .. Integer.sizeof]); data = data[Integer.sizeof .. $]; return value; }