1 module wasm_reader.leb; 2 3 import std.range : ElementType, front, empty, popFront; 4 5 version(unittest) { 6 import unit_threaded; 7 } 8 9 struct varuint(T) { 10 static T decode(Range)(auto ref Range range) { 11 return range.decodeLEBunsigned!T; 12 } 13 } 14 struct varint(T) { 15 static T decode(Range)(auto ref Range range) { 16 return range.decodeLEBsigned!T; 17 } 18 } 19 20 template sizeOf(var) if (is(var : varuint!T, T) || is(var : varint!T, T)) { 21 auto sizeOf(T)(T t) { 22 import core.bitop; 23 return bsr(t) / 7 + 1; 24 } 25 } 26 alias varuint1 = varuint!bool; 27 alias varuint7 = varuint!ubyte; 28 alias varuint32 = varuint!uint; 29 alias varint7 = varint!byte; 30 alias varint32 = varint!int; 31 alias varint64 = varint!long; 32 33 T decodeLEBsigned(T, Range)(auto ref Range range) if (is(ElementType!(Range) == ubyte)) { 34 T result = 0; 35 size_t shift = 0; 36 enum size = T.sizeof * 8; 37 ubyte b = 0; 38 while(!range.empty) { 39 b = range.front(); 40 range.popFront(); 41 result |= ((b & 0x7f) << shift); 42 shift += 7; 43 if ((b & 0x80) == 0) 44 break; 45 } 46 47 if ((shift < size) && (b & 0x40)) 48 result |= (~0 << shift); 49 return result; 50 } 51 52 unittest { 53 import std.stdio; 54 ubyte[] data = [0x9B,0xF1,0x59]; 55 assert(data.decodeLEBsigned!int() == -624485); 56 assert(data.empty); 57 } 58 59 T decodeLEBunsigned(T, Range)(auto ref Range range) if (is(ElementType!(Range) == ubyte)) { 60 T result = 0; 61 size_t shift = 0; 62 while(!range.empty) { 63 ubyte b = range.front(); 64 range.popFront(); 65 static if (T.sizeof < 2) { 66 result = cast(T)(b & 0x7f); 67 } else 68 result |= ((b & 0x7f) << shift); 69 if ((b & 0x80) == 0) 70 break; 71 shift += 7; 72 } 73 return result; 74 } 75 76 unittest { 77 ubyte[] data = [0xe5,0x8e,0x26]; 78 assert(data.decodeLEBunsigned!uint() == 624485); 79 assert(data.empty); 80 } 81 82 unittest { 83 ubyte[] data = [0x00]; 84 assert(data.decodeLEBunsigned!bool() == false); 85 assert(data.empty); 86 } 87 88 unittest { 89 ubyte[] data = [0x01]; 90 assert(data.decodeLEBunsigned!bool() == true); 91 assert(data.empty); 92 }