It seems that the varint encoding function would not work for some integers as input. This should in theory fix this issue. Since the SPK IDs are randomly between 0 and 2**32 - 1, it makes sense that the tests fail only sometimes.
66 lines
1.6 KiB
Dart
66 lines
1.6 KiB
Dart
/// 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<int> 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<int> encodeVarint(int i) {
|
|
assert(i >= 0, "Two's complement is not implemented");
|
|
final ret = List<int>.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;
|
|
}
|