byte-helpers.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.reverseBytes = exports.sliceBytes = exports.bytesMatch = exports.concatTypedArrays = exports.stringToBytes = exports.bytesToString = exports.numberToBytes = exports.bytesToNumber = exports.IS_LITTLE_ENDIAN = exports.IS_BIG_ENDIAN = exports.ENDIANNESS = exports.toBinaryString = exports.toHexString = exports.toUint8 = exports.isTypedArray = exports.isArrayBufferView = exports.padStart = exports.countBytes = exports.countBits = void 0;
  7. var _window = _interopRequireDefault(require("global/window"));
  8. // const log2 = Math.log2 ? Math.log2 : (x) => (Math.log(x) / Math.log(2));
  9. var repeat = function repeat(str, len) {
  10. var acc = '';
  11. while (len--) {
  12. acc += str;
  13. }
  14. return acc;
  15. }; // count the number of bits it would take to represent a number
  16. // we used to do this with log2 but BigInt does not support builtin math
  17. // Math.ceil(log2(x));
  18. var countBits = function countBits(x) {
  19. return x.toString(2).length;
  20. }; // count the number of whole bytes it would take to represent a number
  21. exports.countBits = countBits;
  22. var countBytes = function countBytes(x) {
  23. return Math.ceil(countBits(x) / 8);
  24. };
  25. exports.countBytes = countBytes;
  26. var padStart = function padStart(b, len, str) {
  27. if (str === void 0) {
  28. str = ' ';
  29. }
  30. return (repeat(str, len) + b.toString()).slice(-len);
  31. };
  32. exports.padStart = padStart;
  33. var isArrayBufferView = function isArrayBufferView(obj) {
  34. if (ArrayBuffer.isView === 'function') {
  35. return ArrayBuffer.isView(obj);
  36. }
  37. return obj && obj.buffer instanceof ArrayBuffer;
  38. };
  39. exports.isArrayBufferView = isArrayBufferView;
  40. var isTypedArray = function isTypedArray(obj) {
  41. return isArrayBufferView(obj);
  42. };
  43. exports.isTypedArray = isTypedArray;
  44. var toUint8 = function toUint8(bytes) {
  45. if (bytes instanceof Uint8Array) {
  46. return bytes;
  47. }
  48. if (!Array.isArray(bytes) && !isTypedArray(bytes) && !(bytes instanceof ArrayBuffer)) {
  49. // any non-number or NaN leads to empty uint8array
  50. // eslint-disable-next-line
  51. if (typeof bytes !== 'number' || typeof bytes === 'number' && bytes !== bytes) {
  52. bytes = 0;
  53. } else {
  54. bytes = [bytes];
  55. }
  56. }
  57. return new Uint8Array(bytes && bytes.buffer || bytes, bytes && bytes.byteOffset || 0, bytes && bytes.byteLength || 0);
  58. };
  59. exports.toUint8 = toUint8;
  60. var toHexString = function toHexString(bytes) {
  61. bytes = toUint8(bytes);
  62. var str = '';
  63. for (var i = 0; i < bytes.length; i++) {
  64. str += padStart(bytes[i].toString(16), 2, '0');
  65. }
  66. return str;
  67. };
  68. exports.toHexString = toHexString;
  69. var toBinaryString = function toBinaryString(bytes) {
  70. bytes = toUint8(bytes);
  71. var str = '';
  72. for (var i = 0; i < bytes.length; i++) {
  73. str += padStart(bytes[i].toString(2), 8, '0');
  74. }
  75. return str;
  76. };
  77. exports.toBinaryString = toBinaryString;
  78. var BigInt = _window.default.BigInt || Number;
  79. var BYTE_TABLE = [BigInt('0x1'), BigInt('0x100'), BigInt('0x10000'), BigInt('0x1000000'), BigInt('0x100000000'), BigInt('0x10000000000'), BigInt('0x1000000000000'), BigInt('0x100000000000000'), BigInt('0x10000000000000000')];
  80. var ENDIANNESS = function () {
  81. var a = new Uint16Array([0xFFCC]);
  82. var b = new Uint8Array(a.buffer, a.byteOffset, a.byteLength);
  83. if (b[0] === 0xFF) {
  84. return 'big';
  85. }
  86. if (b[0] === 0xCC) {
  87. return 'little';
  88. }
  89. return 'unknown';
  90. }();
  91. exports.ENDIANNESS = ENDIANNESS;
  92. var IS_BIG_ENDIAN = ENDIANNESS === 'big';
  93. exports.IS_BIG_ENDIAN = IS_BIG_ENDIAN;
  94. var IS_LITTLE_ENDIAN = ENDIANNESS === 'little';
  95. exports.IS_LITTLE_ENDIAN = IS_LITTLE_ENDIAN;
  96. var bytesToNumber = function bytesToNumber(bytes, _temp) {
  97. var _ref = _temp === void 0 ? {} : _temp,
  98. _ref$signed = _ref.signed,
  99. signed = _ref$signed === void 0 ? false : _ref$signed,
  100. _ref$le = _ref.le,
  101. le = _ref$le === void 0 ? false : _ref$le;
  102. bytes = toUint8(bytes);
  103. var fn = le ? 'reduce' : 'reduceRight';
  104. var obj = bytes[fn] ? bytes[fn] : Array.prototype[fn];
  105. var number = obj.call(bytes, function (total, byte, i) {
  106. var exponent = le ? i : Math.abs(i + 1 - bytes.length);
  107. return total + BigInt(byte) * BYTE_TABLE[exponent];
  108. }, BigInt(0));
  109. if (signed) {
  110. var max = BYTE_TABLE[bytes.length] / BigInt(2) - BigInt(1);
  111. number = BigInt(number);
  112. if (number > max) {
  113. number -= max;
  114. number -= max;
  115. number -= BigInt(2);
  116. }
  117. }
  118. return Number(number);
  119. };
  120. exports.bytesToNumber = bytesToNumber;
  121. var numberToBytes = function numberToBytes(number, _temp2) {
  122. var _ref2 = _temp2 === void 0 ? {} : _temp2,
  123. _ref2$le = _ref2.le,
  124. le = _ref2$le === void 0 ? false : _ref2$le;
  125. // eslint-disable-next-line
  126. if (typeof number !== 'bigint' && typeof number !== 'number' || typeof number === 'number' && number !== number) {
  127. number = 0;
  128. }
  129. number = BigInt(number);
  130. var byteCount = countBytes(number);
  131. var bytes = new Uint8Array(new ArrayBuffer(byteCount));
  132. for (var i = 0; i < byteCount; i++) {
  133. var byteIndex = le ? i : Math.abs(i + 1 - bytes.length);
  134. bytes[byteIndex] = Number(number / BYTE_TABLE[i] & BigInt(0xFF));
  135. if (number < 0) {
  136. bytes[byteIndex] = Math.abs(~bytes[byteIndex]);
  137. bytes[byteIndex] -= i === 0 ? 1 : 2;
  138. }
  139. }
  140. return bytes;
  141. };
  142. exports.numberToBytes = numberToBytes;
  143. var bytesToString = function bytesToString(bytes) {
  144. if (!bytes) {
  145. return '';
  146. } // TODO: should toUint8 handle cases where we only have 8 bytes
  147. // but report more since this is a Uint16+ Array?
  148. bytes = Array.prototype.slice.call(bytes);
  149. var string = String.fromCharCode.apply(null, toUint8(bytes));
  150. try {
  151. return decodeURIComponent(escape(string));
  152. } catch (e) {// if decodeURIComponent/escape fails, we are dealing with partial
  153. // or full non string data. Just return the potentially garbled string.
  154. }
  155. return string;
  156. };
  157. exports.bytesToString = bytesToString;
  158. var stringToBytes = function stringToBytes(string, stringIsBytes) {
  159. if (typeof string !== 'string' && string && typeof string.toString === 'function') {
  160. string = string.toString();
  161. }
  162. if (typeof string !== 'string') {
  163. return new Uint8Array();
  164. } // If the string already is bytes, we don't have to do this
  165. // otherwise we do this so that we split multi length characters
  166. // into individual bytes
  167. if (!stringIsBytes) {
  168. string = unescape(encodeURIComponent(string));
  169. }
  170. var view = new Uint8Array(string.length);
  171. for (var i = 0; i < string.length; i++) {
  172. view[i] = string.charCodeAt(i);
  173. }
  174. return view;
  175. };
  176. exports.stringToBytes = stringToBytes;
  177. var concatTypedArrays = function concatTypedArrays() {
  178. for (var _len = arguments.length, buffers = new Array(_len), _key = 0; _key < _len; _key++) {
  179. buffers[_key] = arguments[_key];
  180. }
  181. buffers = buffers.filter(function (b) {
  182. return b && (b.byteLength || b.length) && typeof b !== 'string';
  183. });
  184. if (buffers.length <= 1) {
  185. // for 0 length we will return empty uint8
  186. // for 1 length we return the first uint8
  187. return toUint8(buffers[0]);
  188. }
  189. var totalLen = buffers.reduce(function (total, buf, i) {
  190. return total + (buf.byteLength || buf.length);
  191. }, 0);
  192. var tempBuffer = new Uint8Array(totalLen);
  193. var offset = 0;
  194. buffers.forEach(function (buf) {
  195. buf = toUint8(buf);
  196. tempBuffer.set(buf, offset);
  197. offset += buf.byteLength;
  198. });
  199. return tempBuffer;
  200. };
  201. /**
  202. * Check if the bytes "b" are contained within bytes "a".
  203. *
  204. * @param {Uint8Array|Array} a
  205. * Bytes to check in
  206. *
  207. * @param {Uint8Array|Array} b
  208. * Bytes to check for
  209. *
  210. * @param {Object} options
  211. * options
  212. *
  213. * @param {Array|Uint8Array} [offset=0]
  214. * offset to use when looking at bytes in a
  215. *
  216. * @param {Array|Uint8Array} [mask=[]]
  217. * mask to use on bytes before comparison.
  218. *
  219. * @return {boolean}
  220. * If all bytes in b are inside of a, taking into account
  221. * bit masks.
  222. */
  223. exports.concatTypedArrays = concatTypedArrays;
  224. var bytesMatch = function bytesMatch(a, b, _temp3) {
  225. var _ref3 = _temp3 === void 0 ? {} : _temp3,
  226. _ref3$offset = _ref3.offset,
  227. offset = _ref3$offset === void 0 ? 0 : _ref3$offset,
  228. _ref3$mask = _ref3.mask,
  229. mask = _ref3$mask === void 0 ? [] : _ref3$mask;
  230. a = toUint8(a);
  231. b = toUint8(b); // ie 11 does not support uint8 every
  232. var fn = b.every ? b.every : Array.prototype.every;
  233. return b.length && a.length - offset >= b.length && // ie 11 doesn't support every on uin8
  234. fn.call(b, function (bByte, i) {
  235. var aByte = mask[i] ? mask[i] & a[offset + i] : a[offset + i];
  236. return bByte === aByte;
  237. });
  238. };
  239. exports.bytesMatch = bytesMatch;
  240. var sliceBytes = function sliceBytes(src, start, end) {
  241. if (Uint8Array.prototype.slice) {
  242. return Uint8Array.prototype.slice.call(src, start, end);
  243. }
  244. return new Uint8Array(Array.prototype.slice.call(src, start, end));
  245. };
  246. exports.sliceBytes = sliceBytes;
  247. var reverseBytes = function reverseBytes(src) {
  248. if (src.reverse) {
  249. return src.reverse();
  250. }
  251. return Array.prototype.reverse.call(src);
  252. };
  253. exports.reverseBytes = reverseBytes;