base32.dart 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import 'dart:typed_data' show Uint8List, ByteData;
  2. import 'dart:math' show min;
  3. /// Class for decoding base32 String into List<Int>.
  4. class Base32 {
  5. /// Decodes an [input] base32 String into Uint8List.
  6. static List<int> decode(String input) {
  7. // Map characters to values after removing equal signs
  8. var mapped = input
  9. .split('')
  10. .where((c) => c != '=') // remove '='
  11. .map((c) => _base32Map[c])
  12. .toList();
  13. // Initialise list
  14. // If completed at current index, floor division is sufficient
  15. // If part of previous index, floor division is still sufficient
  16. var length = (mapped.length * 5 / 8).floor();
  17. var bdata = ByteData(length);
  18. // For each byte
  19. for (int i = 0; i < length; i++) {
  20. // Offset of byte in bits
  21. int bitOffset = i * 8;
  22. // Start index and offset
  23. int start = (bitOffset / 5).floor();
  24. int offset = bitOffset % 5;
  25. // Bits to take out of 1st, 2nd and 3rd
  26. int n1 = 5 - offset;
  27. int n2 = min(5, 8 - n1);
  28. int n3 = 8 - n1 - n2;
  29. // print("$start: $n1 $n2 $n3");
  30. // print(Uint8List.view(bdata.buffer));
  31. // Bitwise OR the segments together
  32. int value = mapped[start]! << (8 - n1); // Right-most bits of first
  33. if (n2 > 0 && mapped.length > start + 1) {
  34. value |= (mapped[start + 1]! >> (5 - n2)) << n3; // Left-most and shift
  35. }
  36. if (n3 > 0 && mapped.length > start + 2) {
  37. value |= mapped[start + 2]! >> (5 - n3); // Left-most bits of third
  38. }
  39. bdata.setUint8(i, value);
  40. }
  41. return Uint8List.view(bdata.buffer);
  42. }
  43. /// Determines whether a given string is a valid base32 string.
  44. static bool isBase32(String input) {
  45. return input.split('').every((c) => c == '=' || _base32Map.containsKey(c));
  46. }
  47. /// Decode map
  48. static const _base32Map = {
  49. 'A': 0,
  50. 'B': 1,
  51. 'C': 2,
  52. 'D': 3,
  53. 'E': 4,
  54. 'F': 5,
  55. 'G': 6,
  56. 'H': 7,
  57. 'I': 8,
  58. 'J': 9,
  59. 'K': 10,
  60. 'L': 11,
  61. 'M': 12,
  62. 'N': 13,
  63. 'O': 14,
  64. 'P': 15,
  65. 'Q': 16,
  66. 'R': 17,
  67. 'S': 18,
  68. 'T': 19,
  69. 'U': 20,
  70. 'V': 21,
  71. 'W': 22,
  72. 'X': 23,
  73. 'Y': 24,
  74. 'Z': 25,
  75. '2': 26,
  76. '3': 27,
  77. '4': 28,
  78. '5': 29,
  79. '6': 30,
  80. '7': 31
  81. };
  82. }