/// Masks the 7 LSB const lsb7Mask = 0x7F; /// Constant for setting the MSB const msb = 1 << 7; /// Field types const fieldTypeUint32 = 0; const fieldTypeByteArray = 2; int fieldId(int number, int type) { return (number << 3) | type; } class VarintDecode { const VarintDecode(this.n, this.length); final int n; final int length; } /// Decode a Varint that begins at [input]'s index [offset]. VarintDecode decodeVarint(List input, int offset) { // The return value var n = 0; // The byte offset counter var i = 0; // Iterate until the MSB of the byte is 0 while (true) { // Mask only the 7 LSB and "move" them accordingly n += (input[offset + i] & lsb7Mask) << (7 * i); // Break if we reached the end if (input[offset + i] & 1 << 7 == 0) { break; } i++; } return VarintDecode(n, i + 1); } // Encodes the integer [i] into a Varint. List encodeVarint(int i) { assert(i >= 0, "Two's complement is not implemented"); final ret = List.empty(growable: true); // Thanks to https://github.com/hathibelagal-dev/LEB128 for the trick with toRadixString! final numSevenBlocks = (i.toRadixString(2).length / 7).ceil(); for (var j = 0; j < numSevenBlocks; j++) { // The 7 LSB of the byte we're creating final x = (i & (lsb7Mask << j * 7)) >> j * 7; if (j == numSevenBlocks - 1) { // If we were to shift further, we only get zero, so we're at the end ret.add(x); } else { // We still have at least one bit more to go, so set the MSB to 1 ret.add(x + msb); } } return ret; }