UNPKG

biner

Version:

Declarative binary data encoder / decoder.

148 lines 4.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const decode_1 = require("../decode"); const encode_1 = require("../encode"); const encoding_length_1 = require("../encoding-length"); const util_1 = require("../util"); const meta_1 = require("../internal/meta"); function array(type, length, lengthType = 'count') { if (!util_1.isType(type) && !util_1.isUserType(type)) { throw new TypeError('Argument #1 should be a valid type.'); } const isLengthInBytes = lengthType === 'bytes'; const isnum = typeof length === 'number'; const istype = util_1.isType(length); const isfunc = util_1.isFunction(length); if (!isnum && !istype && !isfunc) { throw new TypeError('Unknown type of argument #1.'); } return { encode, decode, encodingLength, }; function encode(items, wstream) { checkArray(items); const context = meta_1.Metadata.clone(this); let bytes = 0; let expectedSize = 0; if (istype) { expectedSize = items.length; } else if (isnum) { expectedSize = length; } else if (isfunc) { expectedSize = length(context); checkArraySizeType(expectedSize); } if (!isLengthInBytes) { checkArraySize(expectedSize, items.length); } if (isLengthInBytes) { const lengthContext = meta_1.Metadata.clone(context); for (const item of items) { encoding_length_1.encodingLengthCommon(item, type, lengthContext); } if (istype) { expectedSize = lengthContext.bytes; } checkArraySize(lengthContext.bytes, expectedSize); meta_1.Metadata.clean(lengthContext); } if (istype) { const b = length.encode.call(context, expectedSize, wstream); bytes += b; } items.forEach(item => { encode_1.encodeCommon(item, wstream, type, context); }); bytes += context.bytes; meta_1.Metadata.clean(context); return bytes; } function decode(rstream) { let expectedSize = 0; let bytes = 0, count; const context = meta_1.Metadata.clone(this); if (isnum) { expectedSize = length; } else if (istype) { [expectedSize, count] = length.decode.call(context, rstream); bytes += count; } else if (isfunc) { expectedSize = length(context); } checkArraySizeType(expectedSize); let values; if (isLengthInBytes) { values = decodeBytes(type, expectedSize, rstream, context); } else { values = decodeCount(type, expectedSize, rstream, context); } bytes += context.bytes; meta_1.Metadata.clean(context); return [values, bytes]; } function encodingLength(items) { checkArray(items); const context = meta_1.Metadata.clone(this); let size = 0; if (isnum && isLengthInBytes) { return length; } if (istype && !isLengthInBytes) { size = length.encodingLength(items.length); } for (const item of items) { encoding_length_1.encodingLengthCommon(item, type, context); } meta_1.Metadata.clean(context); size += context.bytes; if (istype && isLengthInBytes) { size += length.encodingLength(size); } return size; } } exports.array = array; function checkArray(items) { if (!Array.isArray(items)) { throw new TypeError('Argument #1 should be an Array.'); } } function checkArraySizeType(length) { if (typeof length !== 'number') { throw new TypeError('Length of an array should be a number.'); } } function checkArraySize(requiredSize, havingSize) { if (requiredSize !== havingSize) { throw new Error(`Argument #1 required length ${requiredSize} instead of ${havingSize}`); } } function decodeBytes(type, lengthBytes, rstream, context) { const items = []; const before = context.bytes; let bytes = 0; while (bytes < lengthBytes) { const result = decode_1.decodeCommon(rstream, type, context); items.push(result); bytes = context.bytes - before; } if (bytes > lengthBytes) { throw new Error('Incorrect length of an array.'); } return items; } function decodeCount(type, length, rstream, context) { const items = new Array(length); for (let i = 0; i < length; i += 1) { items[i] = decode_1.decodeCommon(rstream, type, context); } return items; } //# sourceMappingURL=array.js.map