FastBase58DecodingAlphabet function

List<int> FastBase58DecodingAlphabet(
  1. String str,
  2. Alphabet alphabet
)

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 c = 0; // u64
  var t = 0;
  // 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) >> 2, 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--) {
      // Add if cond to avoid overflow
      if (support64) {
        t = outi[j] * 58 + c;
        c = t >> 32;
        outi[j] = t & 0xffffffff;
      } else {
        t = outi[j] * 58 + c;
        c = (outi[j] * 58 + c) ~/ 0xffffffff;
        outi[j] = t & 0xffffffff;
      }
    }
  });

  var mask = ((b58sz % 4) * 8) & 0xffffffff;
  if (mask == 0) {
    mask = 32;
  }
  mask = (mask - 8) & 0xffffffff;

  var outLen = 0;
  for (var j = 0; j < outi.length; j++) {
    for (; mask < 32;) {
      // loop relies on uint overflow
      binu[outLen] = (outi[j] >> mask) & 0xff;
      mask = (mask - 8) & 0xffffffff;
      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);
}