123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646 |
- /* jshint browser: true */
- /* global define, module */
- ( // Module boilerplate to support browser globals and browserify and AMD.
- typeof define === "function" ? function (m) { define("msgpack-js", m); } :
- typeof exports === "object" ? function (m) { module.exports = m(); } :
- function(m){ this.msgpack = m(); }
- )(function () {
- "use strict";
- var exports = {};
- exports.inspect = inspect;
- function inspect(buffer) {
- if (buffer === undefined) return "undefined";
- var view;
- var type;
- if (buffer instanceof ArrayBuffer) {
- type = "ArrayBuffer";
- view = new DataView(buffer);
- }
- else if (buffer instanceof DataView) {
- type = "DataView";
- view = buffer;
- }
- if (!view) return JSON.stringify(buffer);
- var bytes = [];
- for (var i = 0; i < buffer.byteLength; i++) {
- if (i > 20) {
- bytes.push("...");
- break;
- }
- var byte = view.getUint8(i).toString(16);
- if (byte.length === 1) byte = "0" + byte;
- bytes.push(byte);
- }
- return "<" + type + " " + bytes.join(" ") + ">";
- }
- // Encode string as utf8 into dataview at offset
- exports.utf8Write = utf8Write;
- function utf8Write(view, offset, string) {
- var byteLength = view.byteLength;
- for(var i = 0, l = string.length; i < l; i++) {
- var codePoint = string.charCodeAt(i);
- // One byte of UTF-8
- if (codePoint < 0x80) {
- view.setUint8(offset++, codePoint >>> 0 & 0x7f | 0x00);
- continue;
- }
- // Two bytes of UTF-8
- if (codePoint < 0x800) {
- view.setUint8(offset++, codePoint >>> 6 & 0x1f | 0xc0);
- view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
- continue;
- }
- // Three bytes of UTF-8.
- if (codePoint < 0x10000) {
- view.setUint8(offset++, codePoint >>> 12 & 0x0f | 0xe0);
- view.setUint8(offset++, codePoint >>> 6 & 0x3f | 0x80);
- view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
- continue;
- }
- // Four bytes of UTF-8
- if (codePoint < 0x110000) {
- view.setUint8(offset++, codePoint >>> 18 & 0x07 | 0xf0);
- view.setUint8(offset++, codePoint >>> 12 & 0x3f | 0x80);
- view.setUint8(offset++, codePoint >>> 6 & 0x3f | 0x80);
- view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
- continue;
- }
- throw new Error("bad codepoint " + codePoint);
- }
- }
- exports.utf8Read = utf8Read;
- function utf8Read(view, offset, length) {
- var string = "";
- for (var i = offset, end = offset + length; i < end; i++) {
- var byte = view.getUint8(i);
- // One byte character
- if ((byte & 0x80) === 0x00) {
- string += String.fromCharCode(byte);
- continue;
- }
- // Two byte character
- if ((byte & 0xe0) === 0xc0) {
- string += String.fromCharCode(
- ((byte & 0x1f) << 6) |
- (view.getUint8(++i) & 0x3f)
- );
- continue;
- }
- // Three byte character
- if ((byte & 0xf0) === 0xe0) {
- string += String.fromCharCode(
- ((byte & 0x0f) << 12) |
- ((view.getUint8(++i) & 0x3f) << 6) |
- ((view.getUint8(++i) & 0x3f) << 0)
- );
- continue;
- }
- // Four byte character
- if ((byte & 0xf8) === 0xf0) {
- string += String.fromCharCode(
- ((byte & 0x07) << 18) |
- ((view.getUint8(++i) & 0x3f) << 12) |
- ((view.getUint8(++i) & 0x3f) << 6) |
- ((view.getUint8(++i) & 0x3f) << 0)
- );
- continue;
- }
- throw new Error("Invalid byte " + byte.toString(16));
- }
- return string;
- }
- exports.utf8ByteCount = utf8ByteCount;
- function utf8ByteCount(string) {
- var count = 0;
- for(var i = 0, l = string.length; i < l; i++) {
- var codePoint = string.charCodeAt(i);
- if (codePoint < 0x80) {
- count += 1;
- continue;
- }
- if (codePoint < 0x800) {
- count += 2;
- continue;
- }
- if (codePoint < 0x10000) {
- count += 3;
- continue;
- }
- if (codePoint < 0x110000) {
- count += 4;
- continue;
- }
- throw new Error("bad codepoint " + codePoint);
- }
- return count;
- }
- exports.encode = function (value) {
- var buffer = new ArrayBuffer(encodedSize(value));
- var view = new DataView(buffer);
- encode(value, view, 0);
- return buffer;
- };
- exports.decode = decode;
- // https://github.com/msgpack/msgpack/blob/master/spec.md
- // we reserve extension type 0x00 to encode javascript 'undefined'
- function Decoder(view, offset) {
- this.offset = offset || 0;
- this.view = view;
- }
- Decoder.prototype.map = function (length) {
- var value = {};
- for (var i = 0; i < length; i++) {
- var key = this.parse();
- value[key] = this.parse();
- }
- return value;
- };
- Decoder.prototype.bin = function (length) {
- var value = new ArrayBuffer(length);
- (new Uint8Array(value)).set(new Uint8Array(this.view.buffer, this.offset, length), 0);
- this.offset += length;
- return value;
- };
- Decoder.prototype.str = function (length) {
- var value = utf8Read(this.view, this.offset, length);
- this.offset += length;
- return value;
- };
- Decoder.prototype.array = function (length) {
- var value = new Array(length);
- for (var i = 0; i < length; i++) {
- value[i] = this.parse();
- }
- return value;
- };
- Decoder.prototype.parse = function () {
- var type = this.view.getUint8(this.offset);
- var value, length;
- // FixStr
- if ((type & 0xe0) === 0xa0) {
- length = type & 0x1f;
- this.offset++;
- return this.str(length);
- }
- // FixMap
- if ((type & 0xf0) === 0x80) {
- length = type & 0x0f;
- this.offset++;
- return this.map(length);
- }
- // FixArray
- if ((type & 0xf0) === 0x90) {
- length = type & 0x0f;
- this.offset++;
- return this.array(length);
- }
- // Positive FixNum
- if ((type & 0x80) === 0x00) {
- this.offset++;
- return type;
- }
- // Negative Fixnum
- if ((type & 0xe0) === 0xe0) {
- value = this.view.getInt8(this.offset);
- this.offset++;
- return value;
- }
- // Undefined as FixExt1
- if (type === 0xd4 && this.view.getUint8(this.offset + 1) === 0x00) {
- this.offset += 3;
- return undefined;
- }
- switch (type) {
- // str 8
- case 0xd9:
- length = this.view.getUint8(this.offset + 1);
- this.offset += 2;
- return this.str(length);
- // str 16
- case 0xda:
- length = this.view.getUint16(this.offset + 1);
- this.offset += 3;
- return this.str(length);
- // str 32
- case 0xdb:
- length = this.view.getUint32(this.offset + 1);
- this.offset += 5;
- return this.str(length);
- // bin 8
- case 0xc4:
- length = this.view.getUint8(this.offset + 1);
- this.offset += 2;
- return this.bin(length);
- // bin 16
- case 0xc5:
- length = this.view.getUint16(this.offset + 1);
- this.offset += 3;
- return this.bin(length);
- // bin 32
- case 0xc6:
- length = this.view.getUint32(this.offset + 1);
- this.offset += 5;
- return this.bin(length);
- // nil
- case 0xc0:
- this.offset++;
- return null;
- // false
- case 0xc2:
- this.offset++;
- return false;
- // true
- case 0xc3:
- this.offset++;
- return true;
- // uint8
- case 0xcc:
- value = this.view.getUint8(this.offset + 1);
- this.offset += 2;
- return value;
- // uint 16
- case 0xcd:
- value = this.view.getUint16(this.offset + 1);
- this.offset += 3;
- return value;
- // uint 32
- case 0xce:
- value = this.view.getUint32(this.offset + 1);
- this.offset += 5;
- return value;
- // uint 64
- case 0xcf:
- var high = this.view.getUint32(this.offset + 1);
- var low = this.view.getUint32(this.offset + 5);
- value = high*0x100000000 + low;
- this.offset += 9;
- return value;
- // int 8
- case 0xd0:
- value = this.view.getInt8(this.offset + 1);
- this.offset += 2;
- return value;
- // int 16
- case 0xd1:
- value = this.view.getInt16(this.offset + 1);
- this.offset += 3;
- return value;
- // int 32
- case 0xd2:
- value = this.view.getInt32(this.offset + 1);
- this.offset += 5;
- return value;
- // int 64
- case 0xd3:
- var high = this.view.getInt32(this.offset + 1);
- var low = this.view.getUint32(this.offset + 5);
- value = high*0x100000000 + low;
- this.offset += 9;
- return value;
- // map 16
- case 0xde:
- length = this.view.getUint16(this.offset + 1);
- this.offset += 3;
- return this.map(length);
- // map 32
- case 0xdf:
- length = this.view.getUint32(this.offset + 1);
- this.offset += 5;
- return this.map(length);
- // array 16
- case 0xdc:
- length = this.view.getUint16(this.offset + 1);
- this.offset += 3;
- return this.array(length);
- // array 32
- case 0xdd:
- length = this.view.getUint32(this.offset + 1);
- this.offset += 5;
- return this.array(length);
- // float
- case 0xca:
- value = this.view.getFloat32(this.offset + 1);
- this.offset += 5;
- return value;
- // double
- case 0xcb:
- value = this.view.getFloat64(this.offset + 1);
- this.offset += 9;
- return value;
- }
- throw new Error("Unknown type 0x" + type.toString(16));
- };
- function decode(buffer) {
- var view = new DataView(buffer);
- var decoder = new Decoder(view);
- var value = decoder.parse();
- if (decoder.offset !== buffer.byteLength) throw new Error((buffer.byteLength - decoder.offset) + " trailing bytes");
- return value;
- }
- function encode(value, view, offset) {
- var type = typeof value;
- // Strings Bytes
- if (type === "string") {
- var length = utf8ByteCount(value);
- // fix str
- if (length < 0x20) {
- view.setUint8(offset, length | 0xa0);
- utf8Write(view, offset + 1, value);
- return 1 + length;
- }
- // str 8
- if (length < 0x100) {
- view.setUint8(offset, 0xd9);
- view.setUint8(offset + 1, length);
- utf8Write(view, offset + 2, value);
- return 2 + length;
- }
- // str 16
- if (length < 0x10000) {
- view.setUint8(offset, 0xda);
- view.setUint16(offset + 1, length);
- utf8Write(view, offset + 3, value);
- return 3 + length;
- }
- // str 32
- if (length < 0x100000000) {
- view.setUint8(offset, 0xdb);
- view.setUint32(offset + 1, length);
- utf8Write(view, offset + 5, value);
- return 5 + length;
- }
- }
- if (value instanceof ArrayBuffer) {
- var length = value.byteLength;
- // bin 8
- if (length < 0x100) {
- view.setUint8(offset, 0xc4);
- view.setUint8(offset + 1, length);
- (new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 2);
- return 2 + length;
- }
- // bin 16
- if (length < 0x10000) {
- view.setUint8(offset, 0xc5);
- view.setUint16(offset + 1, length);
- (new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 3);
- return 3 + length;
- }
- // bin 32
- if (length < 0x100000000) {
- view.setUint8(offset, 0xc6);
- view.setUint32(offset + 1, length);
- (new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 5);
- return 5 + length;
- }
- }
- if (type === "number") {
- // Floating Point
- if ((value << 0) !== value) {
- view.setUint8(offset, 0xcb);
- view.setFloat64(offset + 1, value);
- return 9;
- }
- // Integers
- if (value >=0) {
- // positive fixnum
- if (value < 0x80) {
- view.setUint8(offset, value);
- return 1;
- }
- // uint 8
- if (value < 0x100) {
- view.setUint8(offset, 0xcc);
- view.setUint8(offset + 1, value);
- return 2;
- }
- // uint 16
- if (value < 0x10000) {
- view.setUint8(offset, 0xcd);
- view.setUint16(offset + 1, value);
- return 3;
- }
- // uint 32
- if (value < 0x100000000) {
- view.setUint8(offset, 0xce);
- view.setUint32(offset + 1, value);
- return 5;
- }
- throw new Error("Number too big 0x" + value.toString(16));
- }
- // negative fixnum
- if (value >= -0x20) {
- view.setInt8(offset, value);
- return 1;
- }
- // int 8
- if (value >= -0x80) {
- view.setUint8(offset, 0xd0);
- view.setInt8(offset + 1, value);
- return 2;
- }
- // int 16
- if (value >= -0x8000) {
- view.setUint8(offset, 0xd1);
- view.setInt16(offset + 1, value);
- return 3;
- }
- // int 32
- if (value >= -0x80000000) {
- view.setUint8(offset, 0xd2);
- view.setInt32(offset + 1, value);
- return 5;
- }
- throw new Error("Number too small -0x" + (-value).toString(16).substr(1));
- }
- // undefined
- if (type === "undefined") {
- view.setUint8(offset, 0xd4); // fixext 1
- view.setUint8(offset + 1, 0); // type (undefined)
- view.setUint8(offset + 2, 0); // data (ignored)
- return 3;
- }
- // null
- if (value === null) {
- view.setUint8(offset, 0xc0);
- return 1;
- }
- // Boolean
- if (type === "boolean") {
- view.setUint8(offset, value ? 0xc3 : 0xc2);
- return 1;
- }
- // Container Types
- if (type === "object") {
- var length, size = 0;
- var isArray = Array.isArray(value);
- if (isArray) {
- length = value.length;
- }
- else {
- var keys = Object.keys(value);
- length = keys.length;
- }
- var size;
- if (length < 0x10) {
- view.setUint8(offset, length | (isArray ? 0x90 : 0x80));
- size = 1;
- }
- else if (length < 0x10000) {
- view.setUint8(offset, isArray ? 0xdc : 0xde);
- view.setUint16(offset + 1, length);
- size = 3;
- }
- else if (length < 0x100000000) {
- view.setUint8(offset, isArray ? 0xdd : 0xdf);
- view.setUint32(offset + 1, length);
- size = 5;
- }
- if (isArray) {
- for (var i = 0; i < length; i++) {
- size += encode(value[i], view, offset + size);
- }
- }
- else {
- for (var i = 0; i < length; i++) {
- var key = keys[i];
- size += encode(key, view, offset + size);
- size += encode(value[key], view, offset + size);
- }
- }
- return size;
- }
- throw new Error("Unknown type " + type);
- }
- function encodedSize(value) {
- var type = typeof value;
- // Raw Bytes
- if (type === "string") {
- var length = utf8ByteCount(value);
- if (length < 0x20) {
- return 1 + length;
- }
- if (length < 0x100) {
- return 2 + length;
- }
- if (length < 0x10000) {
- return 3 + length;
- }
- if (length < 0x100000000) {
- return 5 + length;
- }
- }
- if (value instanceof ArrayBuffer) {
- var length = value.byteLength;
- if (length < 0x100) {
- return 2 + length;
- }
- if (length < 0x10000) {
- return 3 + length;
- }
- if (length < 0x100000000) {
- return 5 + length;
- }
- }
- if (type === "number") {
- // Floating Point
- // double
- if (value << 0 !== value) return 9;
- // Integers
- if (value >=0) {
- // positive fixnum
- if (value < 0x80) return 1;
- // uint 8
- if (value < 0x100) return 2;
- // uint 16
- if (value < 0x10000) return 3;
- // uint 32
- if (value < 0x100000000) return 5;
- // uint 64
- if (value < 0x10000000000000000) return 9;
- throw new Error("Number too big 0x" + value.toString(16));
- }
- // negative fixnum
- if (value >= -0x20) return 1;
- // int 8
- if (value >= -0x80) return 2;
- // int 16
- if (value >= -0x8000) return 3;
- // int 32
- if (value >= -0x80000000) return 5;
- // int 64
- if (value >= -0x8000000000000000) return 9;
- throw new Error("Number too small -0x" + value.toString(16).substr(1));
- }
- // undefined
- if (type === "undefined") return 3;
- // Boolean, null
- if (type === "boolean" || value === null) return 1;
- // Container Types
- if (type === "object") {
- var length, size = 0;
- if (Array.isArray(value)) {
- length = value.length;
- for (var i = 0; i < length; i++) {
- size += encodedSize(value[i]);
- }
- }
- else {
- var keys = Object.keys(value);
- length = keys.length;
- for (var i = 0; i < length; i++) {
- var key = keys[i];
- size += encodedSize(key) + encodedSize(value[key]);
- }
- }
- if (length < 0x10) {
- return 1 + size;
- }
- if (length < 0x10000) {
- return 3 + size;
- }
- if (length < 0x100000000) {
- return 5 + size;
- }
- throw new Error("Array or object too long 0x" + length.toString(16));
- }
- throw new Error("Unknown type " + type);
- }
- return exports;
- });
|