diffusion
Version:
Diffusion JavaScript client
382 lines (381 loc) • 12.4 kB
JavaScript
"use strict";
/**
* @module CBOR
*/
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Encoder = void 0;
/* eslint-disable no-bitwise */
var int64_impl_1 = require("./../data/primitive/int64-impl");
var buffer_output_stream_1 = require("./../io/buffer-output-stream");
var uint8array_1 = require("./../util/uint8array");
var consts_1 = require("./consts");
var TWO_POW_32 = 4294967296;
/**
* Encoder to encode values into CBOR
*/
var Encoder = /** @class */ (function () {
/**
* Create an encoder
*/
function Encoder() {
this.bos = new buffer_output_stream_1.BufferOutputStream();
}
/**
* Write a byte to the output stream
*
* @param byte the byte to wryte
*/
Encoder.prototype.writeByte = function (byte) {
this.bos.write(byte);
};
/**
* Write a `Uint8Array` to the output stream
*
* @param buf the buffer to write
* @param offset the starting position in the buffer
* @param length the number of bytes to write
*/
Encoder.prototype.writeBuffer = function (buf, offset, length) {
if (offset === void 0) { offset = 0; }
if (length === void 0) { length = buf.length; }
this.bos.writeMany(buf, offset, length);
};
/**
* Write an unsigned 16 bit integer to the output stream
*
* @param val the integer to write
*/
Encoder.prototype.writeUint16 = function (val) {
this.writeByte((val >> 8) & 0xff);
this.writeByte(val & 0xff);
};
/**
* Write an unsigned 32 bit integer to the output stream
*
* @param val the integer to write
*/
Encoder.prototype.writeUint32 = function (val) {
this.writeUint16((val >> 16) & 0xffff);
this.writeUint16(val & 0xffff);
};
/**
* Write an unsigned 64 bit integer to the output stream
*
* @param val the integer to write
*/
Encoder.prototype.writeUint64 = function (val) {
this.writeUint32(Math.floor(val / TWO_POW_32));
this.writeUint32(val % TWO_POW_32);
};
/**
* Write a break header to the output stream
*
* @param type the header type
*/
Encoder.prototype.writeBreakHeader = function (type) {
this.writeByte(type << 5 | consts_1.additional.BREAK);
};
/**
* Write a token to the output stream
*
* @param type the token type
* @param val the numeric value associated with the token
*/
Encoder.prototype.writeToken = function (type, val) {
var first = type << 5;
if (val < 24) {
this.writeByte(first | val);
}
else if (val < 256) {
this.writeByte(first | 24);
this.writeByte(val);
}
else if (val < 65536) {
this.writeByte(first | 25);
this.writeUint16(val);
}
else if (val < TWO_POW_32) {
this.writeByte(first | 26);
this.writeUint32(val);
}
else {
this.writeByte(first | 27);
this.writeUint64(val);
}
};
/**
* Write a number of any type to the output stream
*
* @param val the number to write
*/
Encoder.prototype.writeNumber = function (val) {
// determine if the number is int or not
if (val.toString().indexOf('.') > -1) {
/* Because Numbers are 53 bits, always write non-integers as doubles
* Can't bit-twiddle to figure out how to encode, as bitwise operations
* will coerce to a 32-bit integer under the hood.
*/
var buf = uint8array_1.uint8FromDoubleBE(val);
this.writeByte((consts_1.types.SIMPLE << 5) | consts_1.additional.DOUBLE_PRECISION);
this.writeBuffer(buf);
}
else {
if (val < 0) {
this.writeToken(consts_1.types.INT, -1 - val);
}
else {
this.writeToken(consts_1.types.UINT, val);
}
}
};
/**
* Write a string to the output stream
*
* @param val the string to write
*/
Encoder.prototype.writeString = function (val) {
var buf = uint8array_1.uint8FromUtf8(val);
this.writeToken(consts_1.types.STRING, buf.length);
this.writeBuffer(buf);
};
/**
* Write a Binary value to the output stream
*
* @param buf the buffer that contains the binary value
* @param offset the starting position in the buffer
* @param length the number of bytes to write
*/
Encoder.prototype.writeBinary = function (val, offset, length) {
if (length === void 0) { length = val.length; }
this.writeToken(consts_1.types.BYTES, length);
this.writeBuffer(val, offset, length);
};
/**
* Write a boolean to the output stream
*
* @param val the boolean to write
*/
Encoder.prototype.writeBoolean = function (val) {
this.writeToken(consts_1.types.SIMPLE, val ? consts_1.additional.TRUE : consts_1.additional.FALSE);
};
/**
* Write `undefined` to the output stream
*/
Encoder.prototype.writeUndefined = function () {
this.writeToken(consts_1.types.SIMPLE, consts_1.additional.UNDEFINED);
};
/**
* Write `null` to the output stream
*/
Encoder.prototype.writeNull = function () {
this.writeToken(consts_1.types.SIMPLE, consts_1.additional.NULL);
};
/**
* Write an object to the output stream
*
* @param val the object to encode
*/
Encoder.prototype.writeObject = function (val) {
var e_1, _a;
var keys = Object.getOwnPropertyNames(val);
this.startObject();
try {
for (var keys_1 = __values(keys), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
var key = keys_1_1.value;
this.encode(key);
this.encode(val[key]);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (keys_1_1 && !keys_1_1.done && (_a = keys_1.return)) _a.call(keys_1);
}
finally { if (e_1) throw e_1.error; }
}
this.break();
};
/**
* Write an array to the output stream
*
* @param val the array to encode
*/
Encoder.prototype.writeArray = function (val) {
var e_2, _a;
this.startArray();
try {
for (var val_1 = __values(val), val_1_1 = val_1.next(); !val_1_1.done; val_1_1 = val_1.next()) {
var entry = val_1_1.value;
this.encode(entry);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (val_1_1 && !val_1_1.done && (_a = val_1.return)) _a.call(val_1);
}
finally { if (e_2) throw e_2.error; }
}
this.break();
};
/**
* Write a BREAK stop code. This is not constrained by any pre-written strucutural context.
*
* @returns this encoder
*/
Encoder.prototype.break = function () {
this.writeBreakHeader(consts_1.types.SIMPLE);
return this;
};
/**
* Write the header for an array.
*
* Data may be subsequently written. No constraints are applied to subsequent data, i.e the header for a
* fixed-length array may be immediately followed by a break flag
*
* @param length the length of the array. If not provided, this array will be considered
* indefinite-length
*
* @returns this encoder
*/
Encoder.prototype.startArray = function (length) {
if (length === undefined) {
this.writeBreakHeader(consts_1.types.ARRAY);
}
else {
this.writeToken(consts_1.types.ARRAY, length);
}
return this;
};
/**
* Write the header for an object.
*
* Data may be subsequently written. No constraints are applied to subsequent data, i.e the header for a
* fixed-length object may be immediately followed by a break flag
*
* @param length the number of keys in the object. If not provided, this object will be considered
* indefinite-length
*
* @returns this encoder
*/
Encoder.prototype.startObject = function (length) {
if (length === undefined) {
this.writeBreakHeader(consts_1.types.MAP);
}
else {
this.writeToken(consts_1.types.MAP, length);
}
return this;
};
/**
* Write an {@link Int64Impl} value.
*
* @param val the int64 value to encode
* @returns this encoder
*/
Encoder.prototype.writeInt64 = function (val) {
var high = val.getHighBits() | 0;
if (high === 0 || high === -1) {
this.writeNumber(val.toNumber());
}
else {
if (val.isNegative()) {
this.writeByte((consts_1.types.INT << 5) | 27);
var buf = Uint8Array.from(val.toBuffer());
for (var i = 0; i < 8; ++i) {
buf[i] = ~buf[i];
}
this.writeBuffer(buf);
}
else {
this.writeByte((consts_1.types.UINT << 5) | 27);
this.writeBuffer(val.toBuffer());
}
}
return this;
};
/** Write a double value.
*
* @param val the double value to encode
* @returns this encoder
*/
Encoder.prototype.writeDouble = function (val) {
var buf = uint8array_1.uint8FromDoubleBE(val);
this.writeByte((consts_1.types.SIMPLE << 5) | consts_1.additional.DOUBLE_PRECISION);
this.writeBuffer(buf);
return this;
};
/**
* Encode a value to a CBOR representation.
*
* If a buffer is provided, optional offset & length parameters may be provided to
* dictate which bytes are to be encoded.
*
* @param value the value to encode
* @param offset the offset to use if encoding a buffer. Defaults to 0
* @param length the length to use if encoding a buffer. Defaults to the length of the buffer
*
* @returns this encoder
*/
Encoder.prototype.encode = function (value, offset, length) {
if (value instanceof Date) {
this.writeString(value.toJSON());
}
else if (value === null) {
this.writeNull();
}
else if (value === undefined) {
this.writeUndefined();
}
else if (value instanceof int64_impl_1.Int64Impl) {
this.writeInt64(value);
}
else {
switch (typeof value) {
case 'boolean':
this.writeBoolean(value);
break;
case 'string':
this.writeString(value);
break;
case 'number':
this.writeNumber(value);
break;
case 'object':
if (uint8array_1.isUint8Array(value)) {
this.writeBinary(value, offset, length);
}
else if (Array.isArray(value)) {
this.writeArray(value);
}
else {
this.writeObject(value);
}
}
}
return this;
};
/**
* Flush the encoded data and empty the internal buffer
*
* @return the contents of the buffer
*/
Encoder.prototype.flush = function () {
var res = this.bos.getBuffer();
this.bos = new buffer_output_stream_1.BufferOutputStream();
return res;
};
return Encoder;
}());
exports.Encoder = Encoder;