"use strict"; const assert = require("assert"); const timeCall = require("time-call"); const encodeField = require("./encode-field"); const coders = require("./coders"); // TODO: Test if codegen can speed this up, though note that dynamically-created functions execute in global scope *only* // TODO: Enum // FIXME: Default field values // FIXME:regex type module.exports = function createRecordObjectCoder(schema) { return { encode: function (object) { let auxiliaryBlobs = new Map(); let buffers = schema.flatMap(({ name, type: fieldType, required, attributes }) => { // options = { precision, withTimezone, signed, ... } let value = object[name]; let result = encodeField({ asIndexKey: false, name, value, fieldType, required, ... attributes }); if (result.auxiliaryBlob !== undefined) { auxiliaryBlobs.set(result.auxiliaryBlob.key, result.auxiliaryBlob.value); } return result.value; }); return { record: Buffer.concat(buffers), auxiliaryBlobs: auxiliaryBlobs }; }, decode: function (buffer) { let offset = 0; let resultObject = {}; schema.forEach(({ name, type: fieldType, attributes }) => { let result = coders.decode(fieldType, buffer, offset, attributes); if (result.auxiliaryBlob === undefined) { resultObject[name] = result.value; } else { // FIXME resultObject[name] = { _blobKey: result.auxiliaryBlob.key }; } offset += result.bytesRead; }); // Ensure that we've read exactly enough bytes assert(offset === buffer.length); return resultObject; } }; }; // let dummySchema = [ // { name: "username", type: "string", required: true }, // { name: "passwordHash", type: "string", required: true }, // { name: "emailAddress", type: "string" }, // { name: "isActive", type: "boolean", required: true }, // { name: "registrationDate", type: "date", required: true, attributes: { withTimezone: true } }, // { name: "invitesLeft", type: "integer", required: true }, // ]; // let recordCoder = module.exports(dummySchema); // let input = { // username: "joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91joepie91", // passwordHash: "foobar", // emailAddress: "admin@cryto.net", // isActive: true, // registrationDate: new Date, // invitesLeft: 10 // }; // let encoded = recordCoder.encode(input); // let decoded = recordCoder.decode(encoded.record); // // 44 bytes encoded // // 29 characters string // // 15 bytes extra // console.log({ input, encoded, decoded }); // // console.log(timeCall(() => { // // for (let i = 0; i < 1000; i++) { // // recordCoder.encode({ // // username: "joepie91", // // passwordHash: "foobar", // // emailAddress: "admin@cryto.net", // // isActive: true, // // registrationDate: new Date, // // invitesLeft: 10 // // }); // // } // // }));