binary-data
Version:
Declarative binary data encoder / decoder.
73 lines (60 loc) • 1.67 kB
JavaScript
const { isUserType, isType } = require('lib/util');
const Metadata = require('internal/meta');
const symbols = require('internal/symbols');
module.exports = {
encodingLength,
encodingLengthCommon,
};
/**
* Get the number of bytes to encode `obj` using `schema`.
* @param {*} obj Any valid js object.
* @param {Object} schema
* @returns {number}
*/
function encodingLength(obj, schema) {
const context = new Metadata();
encodingLengthCommon(obj, schema, context);
Metadata.clean(context);
return context.bytes;
}
/**
* @param {any} item
* @param {Object} typeOrSchema
* @param {Metadata} context
*/
function encodingLengthCommon(item, typeOrSchema, context) {
if (isType(typeOrSchema)) {
context[symbols.bytes] += typeOrSchema.encodingLength.call(context, item);
} else {
encodingLengthSchema(item, typeOrSchema, context);
}
}
/**
* @param {any} item
* @param {Object} schema
* @param {Metadata} context
*/
function encodingLengthSchema(item, schema, context) {
if (!isUserType(schema)) {
throw new TypeError('Argument `schema` should be a plain object.');
}
if (context.node === undefined) {
context.node = item;
context.current = item;
} else {
context.current = item;
}
const keys = Object.keys(schema);
for (let i = 0; i < keys.length; i += 1) {
const key = keys[i];
const type = schema[key];
const value = item[key];
if (!isType(type)) {
encodingLengthSchema(value, type, context);
context.current = item;
continue; // eslint-disable-line no-continue
}
context[symbols.bytes] += type.encodingLength.call(context, value);
}
}
;