decodeFromBase64 static method

String decodeFromBase64({
  1. required String encoded,
  2. required String charset,
})

Implementation

static String decodeFromBase64({
  required String encoded,
  required String charset,
}) {
  if (encoded.isEmpty) return '';

  int outputLength = encoded.length;
  int n = charset.length;
  if (n < 2)
    throw Exception('Charset must have at least 2 unique characters');

  Map<String, int> charToDigit = {};
  for (int i = 0; i < n; i++) {
    String ch = charset[i];
    if (charToDigit.containsKey(ch)) {
      throw Exception('Charset must have unique characters');
    }
    charToDigit[ch] = i;
  }

  BigInt number = BigInt.zero;
  BigInt base = BigInt.from(n);
  for (int i = 0; i < outputLength; i++) {
    String ch = encoded[i];
    int? digit = charToDigit[ch];
    if (digit == null) throw Exception('Invalid character in encoded string');
    number = number * base + BigInt.from(digit);
  }

  double log2N = log(n) / log(2);
  double maxBits = outputLength * log2N;
  double minBits = (outputLength - 1) * log2N;

  int byteLen = (maxBits / 8).floor();
  int bitLen = byteLen * 8;
  if (!(bitLen > minBits && bitLen <= maxBits)) {
    throw Exception('Invalid encoded length for this charset');
  }

  List<int> bytes = List<int>.filled(byteLen, 0);
  BigInt temp = number;
  for (int i = byteLen - 1; i >= 0; i--) {
    bytes[i] = (temp & BigInt.from(0xFF)).toInt();
    temp = temp >> 8;
  }
  if (temp != BigInt.zero) {
    throw Exception('Number too large for the computed byte length');
  }

  return base64.encode(bytes);
}