FastBase58DecodingAlphabet function
Implementation
List<int> FastBase58DecodingAlphabet(String str, Alphabet alphabet) {
if (str.isEmpty) {
throw Base58Exception('zero length string');
}
var zero = alphabet.encode[0];
var b58sz = str.length;
var zcount = 0;
for (var i = 0; i < b58sz && str.runes.toList()[i] == zero; i++) {
zcount++;
}
var t = 0; // u64
var c = 0; // u64
// the 32bit algo stretches the result up to 2 times
var binu = List<int>.filled(2 * ((b58sz * 406 ~/ 555) + 1), 0); // list<byte>
var outi = List<int>.filled((b58sz + 3) ~/ 4, 0); // list<uint32>
str.runes.forEach((int r) {
if (r > 127) {
throw Base58Exception('high-bit set on invalid digit');
}
if (alphabet.decode[r] == -1) {
throw Base58Exception('invalid base58 digit' + String.fromCharCode(r));
}
c = alphabet.decode[r];
for (var j = outi.length - 1; j >= 0; j--) {
t = (outi[j] * 58 + c).toUnsigned(64);
c = (t >> 32).toUnsigned(64);
outi[j] = (t & 0xffffffff).toUnsigned(32);
}
});
var mask = ((b58sz % 4) * 8).toUnsigned(32);
if (mask == 0) {
mask = 32;
}
mask = (mask - 8).toUnsigned(32);
var outLen = 0;
for (var j = 0; j < outi.length; j++) {
for (; mask < 32;) {
// loop relies on uint overflow
binu[outLen] = (outi[j] >> mask).toUnsigned(8);
mask = (mask - 8).toUnsigned(32);
outLen++;
}
mask = 24;
}
// find the most significant byte post-decode, if any
for (var msb = zcount; msb < binu.length; msb++) {
if (binu[msb] > 0) {
return binu.sublist(msb - zcount, outLen);
}
}
// it's all zeroes
return binu.sublist(0, outLen);
}