'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var common = require('./common.js'); var token = require('./token.js'); var jump = require('./jump.js'); const defaultDecodeOptions = { strict: false, allowIndefinite: true, allowUndefined: true, allowBigInt: true }; class Tokeniser { constructor(data, options = {}) { this.pos = 0; this.data = data; this.options = options; } done() { return this.pos >= this.data.length; } next() { const byt = this.data[this.pos]; let token = jump.quick[byt]; if (token === undefined) { const decoder = jump.jump[byt]; if (!decoder) { throw new Error(`${ common.decodeErrPrefix } no decoder for major type ${ byt >>> 5 } (byte 0x${ byt.toString(16).padStart(2, '0') })`); } const minor = byt & 31; token = decoder(this.data, this.pos, minor, this.options); } this.pos += token.encodedLength; return token; } } const DONE = Symbol.for('DONE'); const BREAK = Symbol.for('BREAK'); function tokenToArray(token, tokeniser, options) { const arr = []; for (let i = 0; i < token.value; i++) { const value = tokensToObject(tokeniser, options); if (value === BREAK) { if (token.value === Infinity) { break; } throw new Error(`${ common.decodeErrPrefix } got unexpected break to lengthed array`); } if (value === DONE) { throw new Error(`${ common.decodeErrPrefix } found array but not enough entries (got ${ i }, expected ${ token.value })`); } arr[i] = value; } return arr; } function tokenToMap(token, tokeniser, options) { const useMaps = options.useMaps === true; const obj = useMaps ? undefined : {}; const m = useMaps ? new Map() : undefined; for (let i = 0; i < token.value; i++) { const key = tokensToObject(tokeniser, options); if (key === BREAK) { if (token.value === Infinity) { break; } throw new Error(`${ common.decodeErrPrefix } got unexpected break to lengthed map`); } if (key === DONE) { throw new Error(`${ common.decodeErrPrefix } found map but not enough entries (got ${ i } [no key], expected ${ token.value })`); } if (useMaps !== true && typeof key !== 'string') { throw new Error(`${ common.decodeErrPrefix } non-string keys not supported (got ${ typeof key })`); } if (options.rejectDuplicateMapKeys === true) { if (useMaps && m.has(key) || !useMaps && key in obj) { throw new Error(`${ common.decodeErrPrefix } found repeat map key "${ key }"`); } } const value = tokensToObject(tokeniser, options); if (value === DONE) { throw new Error(`${ common.decodeErrPrefix } found map but not enough entries (got ${ i } [no value], expected ${ token.value })`); } if (useMaps) { m.set(key, value); } else { obj[key] = value; } } return useMaps ? m : obj; } function tokensToObject(tokeniser, options) { if (tokeniser.done()) { return DONE; } const token$1 = tokeniser.next(); if (token$1.type === token.Type.break) { return BREAK; } if (token$1.type.terminal) { return token$1.value; } if (token$1.type === token.Type.array) { return tokenToArray(token$1, tokeniser, options); } if (token$1.type === token.Type.map) { return tokenToMap(token$1, tokeniser, options); } if (token$1.type === token.Type.tag) { if (options.tags && typeof options.tags[token$1.value] === 'function') { const tagged = tokensToObject(tokeniser, options); return options.tags[token$1.value](tagged); } throw new Error(`${ common.decodeErrPrefix } tag not supported (${ token$1.value })`); } throw new Error('unsupported'); } function decode(data, options) { if (!(data instanceof Uint8Array)) { throw new Error(`${ common.decodeErrPrefix } data to decode must be a Uint8Array`); } options = Object.assign({}, defaultDecodeOptions, options); const tokeniser = options.tokenizer || new Tokeniser(data, options); const decoded = tokensToObject(tokeniser, options); if (decoded === DONE) { throw new Error(`${ common.decodeErrPrefix } did not find any content to decode`); } if (decoded === BREAK) { throw new Error(`${ common.decodeErrPrefix } got unexpected break`); } if (!tokeniser.done()) { throw new Error(`${ common.decodeErrPrefix } too many terminals, data makes no sense`); } return decoded; } exports.Tokeniser = Tokeniser; exports.decode = decode; exports.tokensToObject = tokensToObject;