summaryrefslogtreecommitdiff
path: root/node_modules/capnp-ts/src/util.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/capnp-ts/src/util.js')
-rw-r--r--node_modules/capnp-ts/src/util.js349
1 files changed, 349 insertions, 0 deletions
diff --git a/node_modules/capnp-ts/src/util.js b/node_modules/capnp-ts/src/util.js
new file mode 100644
index 0000000..e29e69e
--- /dev/null
+++ b/node_modules/capnp-ts/src/util.js
@@ -0,0 +1,349 @@
+"use strict";
+/**
+ * @author jdiaz5513
+ */
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.repeat = exports.padToWord = exports.pad = exports.identity = exports.format = exports.encodeUtf8 = exports.dumpBuffer = exports.decodeUtf8 = exports.checkUint32 = exports.checkInt32 = exports.bufferToHex = void 0;
+const tslib_1 = require("tslib");
+// LINT: a lot of the util functions need the any type.
+/* tslint:disable:no-any no-unsafe-any */
+const debug_1 = tslib_1.__importDefault(require("debug"));
+const constants_1 = require("./constants");
+const errors_1 = require("./errors");
+const trace = debug_1.default("capnp:util");
+trace("load");
+/**
+ * Dump a hex string from the given buffer.
+ *
+ * @export
+ * @param {ArrayBuffer} buffer The buffer to convert.
+ * @returns {string} A hexadecimal string representing the buffer.
+ */
+function bufferToHex(buffer) {
+ const a = new Uint8Array(buffer);
+ const h = [];
+ for (let i = 0; i < a.byteLength; i++)
+ h.push(pad(a[i].toString(16), 2));
+ return `[${h.join(" ")}]`;
+}
+exports.bufferToHex = bufferToHex;
+/**
+ * Throw an error if the provided value cannot be represented as a 32-bit integer.
+ *
+ * @export
+ * @param {number} value The number to check.
+ * @returns {number} The same number if it is valid.
+ */
+function checkInt32(value) {
+ if (value > constants_1.MAX_INT32 || value < -constants_1.MAX_INT32) {
+ throw new RangeError(errors_1.RANGE_INT32_OVERFLOW);
+ }
+ return value;
+}
+exports.checkInt32 = checkInt32;
+function checkUint32(value) {
+ if (value < 0 || value > constants_1.MAX_UINT32) {
+ throw new RangeError(errors_1.RANGE_UINT32_OVERFLOW);
+ }
+ return value;
+}
+exports.checkUint32 = checkUint32;
+/**
+ * Decode a UTF-8 encoded byte array into a JavaScript string (UCS-2).
+ *
+ * @export
+ * @param {Uint8Array} src A utf-8 encoded byte array.
+ * @returns {string} A string representation of the byte array.
+ */
+function decodeUtf8(src) {
+ // This ain't for the faint of heart, kids. If you suffer from seizures, heart palpitations, or have had a history of
+ // stroke you may want to look away now.
+ const l = src.byteLength;
+ let dst = "";
+ let i = 0;
+ let cp = 0;
+ let a = 0;
+ let b = 0;
+ let c = 0;
+ let d = 0;
+ while (i < l) {
+ a = src[i++];
+ if ((a & 0b10000000) === 0) {
+ cp = a;
+ }
+ else if ((a & 0b11100000) === 0b11000000) {
+ if (i >= l)
+ throw new RangeError(errors_1.RANGE_INVALID_UTF8);
+ b = src[i++];
+ cp = ((a & 0b00011111) << 6) | (b & 0b00111111);
+ }
+ else if ((a & 0b11110000) === 0b11100000) {
+ if (i + 1 >= l)
+ throw new RangeError(errors_1.RANGE_INVALID_UTF8);
+ b = src[i++];
+ c = src[i++];
+ cp = ((a & 0b00001111) << 12) | ((b & 0b00111111) << 6) | (c & 0b00111111);
+ }
+ else if ((a & 0b11111000) === 0b11110000) {
+ if (i + 2 >= l)
+ throw new RangeError(errors_1.RANGE_INVALID_UTF8);
+ b = src[i++];
+ c = src[i++];
+ d = src[i++];
+ cp = ((a & 0b00000111) << 18) | ((b & 0b00111111) << 12) | ((c & 0b00111111) << 6) | (d & 0b00111111);
+ }
+ else {
+ throw new RangeError(errors_1.RANGE_INVALID_UTF8);
+ }
+ if (cp <= 0xd7ff || (cp >= 0xe000 && cp <= 0xffff)) {
+ dst += String.fromCharCode(cp);
+ }
+ else {
+ // We must reach into the astral plane and construct the surrogate pair!
+ cp -= 0x00010000;
+ const hi = (cp >>> 10) + 0xd800;
+ const lo = (cp & 0x03ff) + 0xdc00;
+ if (hi < 0xd800 || hi > 0xdbff)
+ throw new RangeError(errors_1.RANGE_INVALID_UTF8);
+ dst += String.fromCharCode(hi, lo);
+ }
+ }
+ return dst;
+}
+exports.decodeUtf8 = decodeUtf8;
+function dumpBuffer(buffer) {
+ const b = buffer instanceof ArrayBuffer
+ ? new Uint8Array(buffer)
+ : new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
+ const byteLength = Math.min(b.byteLength, constants_1.MAX_BUFFER_DUMP_BYTES);
+ let r = format("\n=== buffer[%d] ===", byteLength);
+ for (let j = 0; j < byteLength; j += 16) {
+ r += `\n${pad(j.toString(16), 8)}: `;
+ let s = "";
+ let k;
+ for (k = 0; k < 16 && j + k < b.byteLength; k++) {
+ const v = b[j + k];
+ r += `${pad(v.toString(16), 2)} `;
+ // Printable ASCII range.
+ s += v > 31 && v < 255 ? String.fromCharCode(v) : "ยท";
+ if (k === 7)
+ r += " ";
+ }
+ r += `${repeat((17 - k) * 3, " ")}${s}`;
+ }
+ r += "\n";
+ if (byteLength !== b.byteLength) {
+ r += format("=== (truncated %d bytes) ===\n", b.byteLength - byteLength);
+ }
+ return r;
+}
+exports.dumpBuffer = dumpBuffer;
+/**
+ * Encode a JavaScript string (UCS-2) to a UTF-8 encoded string inside a Uint8Array.
+ *
+ * Note that the underlying buffer for the array will likely be larger than the actual contents; ignore the extra bytes.
+ *
+ * @export
+ * @param {string} src The input string.
+ * @returns {Uint8Array} A UTF-8 encoded buffer with the string's contents.
+ */
+function encodeUtf8(src) {
+ const l = src.length;
+ const dst = new Uint8Array(new ArrayBuffer(l * 4));
+ let j = 0;
+ for (let i = 0; i < l; i++) {
+ const c = src.charCodeAt(i);
+ if (c <= 0x7f) {
+ dst[j++] = c;
+ }
+ else if (c <= 0x07ff) {
+ dst[j++] = 0b11000000 | (c >>> 6);
+ dst[j++] = 0b10000000 | ((c >>> 0) & 0b00111111);
+ }
+ else if (c <= 0xd7ff || c >= 0xe000) {
+ dst[j++] = 0b11100000 | (c >>> 12);
+ dst[j++] = 0b10000000 | ((c >>> 6) & 0b00111111);
+ dst[j++] = 0b10000000 | ((c >>> 0) & 0b00111111);
+ }
+ else {
+ // Make sure the surrogate pair is complete.
+ /* istanbul ignore next */
+ if (i + 1 >= l)
+ throw new RangeError(errors_1.RANGE_INVALID_UTF8);
+ // I cast thee back into the astral plane.
+ const hi = c - 0xd800;
+ const lo = src.charCodeAt(++i) - 0xdc00;
+ const cp = ((hi << 10) | lo) + 0x00010000;
+ dst[j++] = 0b11110000 | (cp >>> 18);
+ dst[j++] = 0b10000000 | ((cp >>> 12) & 0b00111111);
+ dst[j++] = 0b10000000 | ((cp >>> 6) & 0b00111111);
+ dst[j++] = 0b10000000 | ((cp >>> 0) & 0b00111111);
+ }
+ }
+ return dst.subarray(0, j);
+}
+exports.encodeUtf8 = encodeUtf8;
+/**
+ * Produce a `printf`-style string. Nice for providing arguments to `assert` without paying the cost for string
+ * concatenation up front. Precision is supported for floating point numbers.
+ *
+ * @param {string} s The format string. Supported format specifiers: b, c, d, f, j, o, s, x, and X.
+ * @param {...any} args Values to be formatted in the string. Arguments beyond what are consumed by the format string
+ * are ignored.
+ * @returns {string} The formatted string.
+ */
+function format(s, ...args) {
+ const n = s.length;
+ let arg;
+ let argIndex = 0;
+ let c;
+ let escaped = false;
+ let i = 0;
+ let leadingZero = false;
+ let precision;
+ let result = "";
+ function nextArg() {
+ return args[argIndex++];
+ }
+ function slurpNumber() {
+ let digits = "";
+ while (/\d/.test(s[i])) {
+ digits += s[i++];
+ c = s[i];
+ }
+ return digits.length > 0 ? parseInt(digits, 10) : null;
+ }
+ for (; i < n; ++i) {
+ c = s[i];
+ if (escaped) {
+ escaped = false;
+ if (c === ".") {
+ leadingZero = false;
+ c = s[++i];
+ }
+ else if (c === "0" && s[i + 1] === ".") {
+ leadingZero = true;
+ i += 2;
+ c = s[i];
+ }
+ else {
+ leadingZero = true;
+ }
+ precision = slurpNumber();
+ switch (c) {
+ case "a": // number in hex with padding
+ result += "0x" + pad(parseInt(String(nextArg()), 10).toString(16), 8);
+ break;
+ case "b": // number in binary
+ result += parseInt(String(nextArg()), 10).toString(2);
+ break;
+ case "c": // character
+ arg = nextArg();
+ if (typeof arg === "string" || arg instanceof String) {
+ result += arg;
+ }
+ else {
+ result += String.fromCharCode(parseInt(String(arg), 10));
+ }
+ break;
+ case "d": // number in decimal
+ result += parseInt(String(nextArg()), 10);
+ break;
+ case "f": {
+ // floating point number
+ const tmp = parseFloat(String(nextArg())).toFixed(precision || 6);
+ result += leadingZero ? tmp : tmp.replace(/^0/, "");
+ break;
+ }
+ case "j": // JSON
+ result += JSON.stringify(nextArg());
+ break;
+ case "o": // number in octal
+ result += "0" + parseInt(String(nextArg()), 10).toString(8);
+ break;
+ case "s": // string
+ result += nextArg();
+ break;
+ case "x": // lowercase hexadecimal
+ result += "0x" + parseInt(String(nextArg()), 10).toString(16);
+ break;
+ case "X": // uppercase hexadecimal
+ result += "0x" + parseInt(String(nextArg()), 10).toString(16).toUpperCase();
+ break;
+ default:
+ result += c;
+ break;
+ }
+ }
+ else if (c === "%") {
+ escaped = true;
+ }
+ else {
+ result += c;
+ }
+ }
+ return result;
+}
+exports.format = format;
+/**
+ * Return the thing that was passed in. Yaaaaawn.
+ *
+ * @export
+ * @template T
+ * @param {T} x A thing.
+ * @returns {T} The same thing.
+ */
+function identity(x) {
+ return x;
+}
+exports.identity = identity;
+function pad(v, width, pad = "0") {
+ return v.length >= width ? v : new Array(width - v.length + 1).join(pad) + v;
+}
+exports.pad = pad;
+/**
+ * Add padding to a number to make it divisible by 8. Typically used to pad byte sizes so they align to a word boundary.
+ *
+ * @export
+ * @param {number} size The number to pad.
+ * @returns {number} The padded number.
+ */
+function padToWord(size) {
+ return (size + 7) & ~7;
+}
+exports.padToWord = padToWord;
+/**
+ * Repeat a string n times. Shamelessly copied from lodash.repeat.
+ *
+ * @param {number} times Number of times to repeat.
+ * @param {string} str The string to repeat.
+ * @returns {string} The repeated string.
+ */
+function repeat(times, str) {
+ let out = "";
+ let n = times;
+ let s = str;
+ if (n < 1 || n > Number.MAX_VALUE)
+ return out;
+ // https://en.wikipedia.org/wiki/Exponentiation_by_squaring
+ do {
+ if (n % 2)
+ out += s;
+ n = Math.floor(n / 2);
+ if (n)
+ s += s;
+ } while (n);
+ return out;
+}
+exports.repeat = repeat;
+const hex = (v) => parseInt(String(v)).toString(16);
+// Set up custom debug formatters.
+/* istanbul ignore next */
+debug_1.default.formatters["h"] = hex;
+/* istanbul ignore next */
+debug_1.default.formatters["x"] = (v) => `0x${hex(v)}`;
+/* istanbul ignore next */
+debug_1.default.formatters["a"] = (v) => `0x${pad(hex(v), 8)}`;
+/* istanbul ignore next */
+debug_1.default.formatters["X"] = (v) => `0x${hex(v).toUpperCase()}`;
+//# sourceMappingURL=util.js.map \ No newline at end of file