diffusion
Version:
Diffusion JavaScript client
182 lines (181 loc) • 6.59 kB
JavaScript
;
/**
* @module CBOR
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.isAny = exports.isString = exports.isInt64 = exports.isDouble = exports.Decoder = void 0;
var uint8array_1 = require("./../util/uint8array");
var errors_1 = require("../../errors/errors");
var consts_1 = require("./consts");
var tokeniser_1 = require("./tokeniser");
/**
* Recursive token-parsing function; will evaluate tokens and build up complete object representations in order.
*
* @throws an {@link InvalidDataError} if there was an error parsing the next value
*/
/* eslint-disable-next-line complexity */
function decode(token, tokeniser) {
switch (token.type) {
case consts_1.tokens.VALUE:
return token.value;
case consts_1.tokens.MAP_START:
var obj = {};
for (;;) {
var field = tokeniser.nextToken();
if (field === null) {
throw new errors_1.InvalidDataError('Unexpected EOF (reading: map key)');
}
if (field.type === consts_1.tokens.MAP_END) {
break;
}
var value = tokeniser.nextToken();
if (value === null || value.type === consts_1.tokens.MAP_END) {
throw new errors_1.InvalidDataError('Unexpected EOF (reading: map value)');
}
var key = decode(field, tokeniser);
if (key === undefined || key === null) {
throw new errors_1.InvalidDataError('Cannot have undefined key (reading: map key)');
}
obj[key.toString()] = decode(value, tokeniser);
}
return obj;
case consts_1.tokens.ARRAY_START:
var arr = [];
for (;;) {
var element = tokeniser.nextToken();
if (element === null) {
throw new errors_1.InvalidDataError('Unexpected EOF (reading: array value)');
}
if (element.type === consts_1.tokens.ARRAY_END) {
break;
}
arr.push(decode(element, tokeniser));
}
return arr;
case consts_1.tokens.STRING_START:
var chunks = [];
for (;;) {
var chunk = tokeniser.nextToken();
if (chunk === null) {
throw new errors_1.InvalidDataError('Unexpected EOF (reading: indefinite-length string');
}
if (chunk.type === consts_1.tokens.STRING_END) {
break;
}
if (chunk.header.type !== token.header.type) {
throw new errors_1.InvalidDataError('Unexpected chunk type (' + chunk.header.type + ') within string');
}
chunks.push(chunk.value);
}
switch (token.header.type) {
case consts_1.types.BYTES:
return uint8array_1.concatUint8Arrays(chunks);
case consts_1.types.STRING:
return chunks.join('');
default:
throw new errors_1.InvalidDataError('Unexpected chunk type ('
+ token.header.type + ') (reading: string)');
}
default:
throw new errors_1.InvalidDataError('Unexpected token: ' + JSON.stringify(token));
}
}
/**
* Provide a higher-level interface around Tokeniser, to enable the reading of
* complex values as represented in arrays/objects etc.
*/
var Decoder = /** @class */ (function () {
/**
* Create a decoder
*
* @param initial the `Uint8Array` or `Tokeniser` to read from
* @param offset if a `Uint8Array` is supplied as first argument, the optional
* offset from which to start reading. Ignored otherwise.
* @param length if a `Uint8Array` is supplied as first argument, the optional
* number of bytes to read. Ignored otherwise.
*/
function Decoder(initial, offset, length) {
this.tokeniser = (uint8array_1.isUint8Array(initial)) ? new tokeniser_1.Tokeniser(initial, offset, length) : initial;
}
/**
* Check if more tokens can be read from the tokeniser
*
* @return `true` if there are more tokens
*/
Decoder.prototype.hasRemaining = function () {
return this.tokeniser.hasRemaining();
};
/**
* Return the next value, parsed recursively.
*
* If no tokens can be read, a read error will be thrown.
*
* @return the next value
* @throws an {@link InvalidDataError} if no value can be read
*/
Decoder.prototype.nextValue = function () {
return this.nextValueExpecting(isAny);
};
/**
* Return the next value, if its CBOR type is acceptable to `cborTypePredicate`
*
* @parame cborTypePredicate a predicate that should return true if the
* CBOR type is acceptable, false otherwise.
* @return the next value
* @throws an {@link InvalidDataError} if no value can be read
*/
Decoder.prototype.nextValueExpecting = function (cborTypePredicate) {
if (!this.tokeniser.hasRemaining()) {
throw new errors_1.InvalidDataError('Token stream exhausted');
}
var token = this.tokeniser.nextToken();
if (cborTypePredicate(token.header.type)) {
return decode(token, this.tokeniser);
}
else {
throw new errors_1.InvalidDataError('Unexpected CBOR type');
}
};
return Decoder;
}());
exports.Decoder = Decoder;
/**
* Allow only floating point CBOR types
*
* @param cborType the CBOR type
* @return `true` if the type is a floating point number
*/
function isDouble(cborType) {
return cborType === consts_1.types.FLOAT;
}
exports.isDouble = isDouble;
/**
* Allow only int CBOR types
*
* @param cborType the CBOR type
* @return `true` if the type is an integer
*/
function isInt64(cborType) {
return cborType === consts_1.types.UINT ||
cborType === consts_1.types.INT;
}
exports.isInt64 = isInt64;
/**
* Allow only string CBOR types
*
* @param cborType the CBOR type
* @return `true` if the type is a string
*/
function isString(cborType) {
return cborType === consts_1.types.STRING;
}
exports.isString = isString;
/**
* Allow any CBOR types
*
* @return will always return `true`
*/
function isAny() {
return true;
}
exports.isAny = isAny;