summaryrefslogtreecommitdiffstats
path: root/devtools/client/netmonitor/src/components/messages/cbor.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--devtools/client/netmonitor/src/components/messages/cbor.js270
1 files changed, 270 insertions, 0 deletions
diff --git a/devtools/client/netmonitor/src/components/messages/cbor.js b/devtools/client/netmonitor/src/components/messages/cbor.js
new file mode 100644
index 0000000000..8b8b249391
--- /dev/null
+++ b/devtools/client/netmonitor/src/components/messages/cbor.js
@@ -0,0 +1,270 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-2016 Patrick Gansterer <paroga@paroga.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+"use strict";
+const POW_2_24 = 5.960464477539063e-8;
+const POW_2_32 = 4294967296;
+
+function decode(data, tagger, simpleValue) {
+ const dataView = new DataView(data);
+ let offset = 0;
+
+ if (typeof tagger !== "function") {
+ tagger = function (value) {
+ return value;
+ };
+ }
+ if (typeof simpleValue !== "function") {
+ simpleValue = function () {
+ return undefined;
+ };
+ }
+
+ function commitRead(length, value) {
+ offset += length;
+ return value;
+ }
+ function readArrayBuffer(length) {
+ return commitRead(length, new Uint8Array(data, offset, length));
+ }
+ function readFloat16() {
+ const tempArrayBuffer = new ArrayBuffer(4);
+ const tempDataView = new DataView(tempArrayBuffer);
+ const value = readUint16();
+
+ const sign = value & 0x8000;
+ let exponent = value & 0x7c00;
+ const fraction = value & 0x03ff;
+
+ if (exponent === 0x7c00) {
+ exponent = 0xff << 10;
+ } else if (exponent !== 0) {
+ exponent += (127 - 15) << 10;
+ } else if (fraction !== 0) {
+ return (sign ? -1 : 1) * fraction * POW_2_24;
+ }
+
+ tempDataView.setUint32(
+ 0,
+ (sign << 16) | (exponent << 13) | (fraction << 13)
+ );
+ return tempDataView.getFloat32(0);
+ }
+ function readFloat32() {
+ return commitRead(4, dataView.getFloat32(offset));
+ }
+ function readFloat64() {
+ return commitRead(8, dataView.getFloat64(offset));
+ }
+ function readUint8() {
+ return commitRead(1, dataView.getUint8(offset));
+ }
+ function readUint16() {
+ return commitRead(2, dataView.getUint16(offset));
+ }
+ function readUint32() {
+ return commitRead(4, dataView.getUint32(offset));
+ }
+ function readUint64() {
+ return readUint32() * POW_2_32 + readUint32();
+ }
+ function readBreak() {
+ if (dataView.getUint8(offset) !== 0xff) {
+ return false;
+ }
+ offset += 1;
+ return true;
+ }
+ function readLength(additionalInformation) {
+ if (additionalInformation < 24) {
+ return additionalInformation;
+ }
+ if (additionalInformation === 24) {
+ return readUint8();
+ }
+ if (additionalInformation === 25) {
+ return readUint16();
+ }
+ if (additionalInformation === 26) {
+ return readUint32();
+ }
+ if (additionalInformation === 27) {
+ return readUint64();
+ }
+ if (additionalInformation === 31) {
+ return -1;
+ }
+ throw new Error("Invalid length encoding");
+ }
+ function readIndefiniteStringLength(majorType) {
+ const initialByte = readUint8();
+ if (initialByte === 0xff) {
+ return -1;
+ }
+ const length = readLength(initialByte & 0x1f);
+ if (length < 0 || initialByte >> 5 !== majorType) {
+ throw new Error("Invalid indefinite length element");
+ }
+ return length;
+ }
+
+ function appendUtf16Data(utf16data, length) {
+ for (let i = 0; i < length; ++i) {
+ let value = readUint8();
+ if (value & 0x80) {
+ if (value < 0xe0) {
+ value = ((value & 0x1f) << 6) | (readUint8() & 0x3f);
+ length -= 1;
+ } else if (value < 0xf0) {
+ value =
+ ((value & 0x0f) << 12) |
+ ((readUint8() & 0x3f) << 6) |
+ (readUint8() & 0x3f);
+ length -= 2;
+ } else {
+ value =
+ ((value & 0x0f) << 18) |
+ ((readUint8() & 0x3f) << 12) |
+ ((readUint8() & 0x3f) << 6) |
+ (readUint8() & 0x3f);
+ length -= 3;
+ }
+ }
+
+ if (value < 0x10000) {
+ utf16data.push(value);
+ } else {
+ value -= 0x10000;
+ utf16data.push(0xd800 | (value >> 10));
+ utf16data.push(0xdc00 | (value & 0x3ff));
+ }
+ }
+ }
+
+ // eslint-disable-next-line complexity
+ function decodeItem() {
+ const initialByte = readUint8();
+ const majorType = initialByte >> 5;
+ const additionalInformation = initialByte & 0x1f;
+ let i;
+ let length;
+
+ if (majorType === 7) {
+ switch (additionalInformation) {
+ case 25:
+ return readFloat16();
+ case 26:
+ return readFloat32();
+ case 27:
+ return readFloat64();
+ }
+ }
+
+ length = readLength(additionalInformation);
+ if (length < 0 && (majorType < 2 || majorType > 6)) {
+ throw new Error("Invalid length");
+ }
+
+ switch (majorType) {
+ case 0:
+ return length;
+ case 1:
+ return -1 - length;
+ case 2:
+ if (length < 0) {
+ const elements = [];
+ let fullArrayLength = 0;
+ while ((length = readIndefiniteStringLength(majorType)) >= 0) {
+ fullArrayLength += length;
+ elements.push(readArrayBuffer(length));
+ }
+ const fullArray = new Uint8Array(fullArrayLength);
+ let fullArrayOffset = 0;
+ for (i = 0; i < elements.length; ++i) {
+ fullArray.set(elements[i], fullArrayOffset);
+ fullArrayOffset += elements[i].length;
+ }
+ return fullArray;
+ }
+ return readArrayBuffer(length);
+ case 3:
+ const utf16data = [];
+ if (length < 0) {
+ while ((length = readIndefiniteStringLength(majorType)) >= 0) {
+ appendUtf16Data(utf16data, length);
+ }
+ } else {
+ appendUtf16Data(utf16data, length);
+ }
+ return String.fromCharCode.apply(null, utf16data);
+ case 4:
+ let retArray;
+ if (length < 0) {
+ retArray = [];
+ while (!readBreak()) {
+ retArray.push(decodeItem());
+ }
+ } else {
+ retArray = new Array(length);
+ for (i = 0; i < length; ++i) {
+ retArray[i] = decodeItem();
+ }
+ }
+ return retArray;
+ case 5:
+ const retObject = {};
+ for (i = 0; i < length || (length < 0 && !readBreak()); ++i) {
+ const key = decodeItem();
+ retObject[key] = decodeItem();
+ }
+ return retObject;
+ case 6:
+ return tagger(decodeItem(), length);
+ case 7:
+ switch (length) {
+ case 20:
+ return false;
+ case 21:
+ return true;
+ case 22:
+ return null;
+ case 23:
+ return undefined;
+ default:
+ return simpleValue(length);
+ }
+ }
+
+ throw new Error("Invalid major byte");
+ }
+
+ const ret = decodeItem();
+ if (offset !== data.byteLength) {
+ throw new Error("Remaining bytes");
+ }
+
+ return ret;
+}
+
+module.exports = { decode };