@jsonjoy.com/json-type
Version:
High-performance JSON Pointer implementation
121 lines • 6.76 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MsgPackCodegen = void 0;
const tslib_1 = require("tslib");
const JsExpression_1 = require("@jsonjoy.com/codegen/lib/util/JsExpression");
const normalizeAccessor_1 = require("@jsonjoy.com/codegen/lib/util/normalizeAccessor");
const MsgPackEncoder_1 = require("@jsonjoy.com/json-pack/lib/msgpack/MsgPackEncoder");
const type_1 = require("../../../type");
const util_1 = require("../../util");
const AbstractBinaryCodegen_1 = require("../AbstractBinaryCodegen");
const writer_1 = require("../writer");
const once_1 = require("thingies/lib/once");
let MsgPackCodegen = (() => {
var _a;
let _classSuper = AbstractBinaryCodegen_1.AbstractBinaryCodegen;
let _instanceExtraInitializers = [];
let _linkGet_decorators;
return _a = class MsgPackCodegen extends _classSuper {
constructor() {
super(...arguments);
this.encoder = (tslib_1.__runInitializers(this, _instanceExtraInitializers), new MsgPackEncoder_1.MsgPackEncoder(writer_1.writer));
}
linkGet() {
this.codegen.linkDependency(_a.get, 'get');
}
onObj(path, value, type) {
const codegen = this.codegen;
const r = codegen.r();
const fields = type.keys;
const length = fields.length;
const requiredFields = fields.filter((field) => !(field instanceof type_1.KeyOptType));
const optionalFields = fields.filter((field) => field instanceof type_1.KeyOptType);
const requiredLength = requiredFields.length;
const optionalLength = optionalFields.length;
const totalMaxKnownFields = requiredLength + optionalLength;
if (totalMaxKnownFields > 0xffff)
throw new Error('Too many fields');
const encodeUnknownFields = !!type.schema.encodeUnknownKeys;
const rFieldCount = codegen.r();
const emitRequiredFields = () => {
for (let i = 0; i < requiredLength; i++) {
const field = requiredFields[i];
this.blob(this.gen((encoder) => encoder.writeStr(field.key)));
const accessor = (0, normalizeAccessor_1.normalizeAccessor)(field.key);
this.onNode([...path, field.key], new JsExpression_1.JsExpression(() => `${r}${accessor}`), field.val);
}
};
const emitOptionalFields = () => {
for (let i = 0; i < optionalLength; i++) {
const field = optionalFields[i];
const accessor = (0, normalizeAccessor_1.normalizeAccessor)(field.key);
codegen.if(`${r}${accessor} !== undefined`, () => {
codegen.js(`${rFieldCount}++;`);
this.blob(this.gen((encoder) => encoder.writeStr(field.key)));
this.onNode([...path, field.key], new JsExpression_1.JsExpression(() => `${r}${accessor}`), field.val);
});
}
};
const emitUnknownFields = () => {
const ri = codegen.r();
const rKeys = codegen.r();
const rKey = codegen.r();
const rLength = codegen.r();
const keys = fields.map((field) => JSON.stringify(field.key));
const rKnownFields = codegen.addConstant(`new Set([${keys.join(',')}])`);
codegen.js(`var ${rKeys} = Object.keys(${r}), ${rLength} = ${rKeys}.length, ${rKey};`);
codegen.js(`for (var ${ri} = 0; ${ri} < ${rLength}; ${ri}++) {`);
codegen.js(`${rKey} = ${rKeys}[${ri}];`);
codegen.js(`if (${rKnownFields}.has(${rKey})) continue;`);
codegen.js(`${rFieldCount}++;`);
codegen.js(`encoder.writeStr(${rKey});`);
codegen.js(`encoder.writeAny(${r}[${rKey}]);`);
codegen.js(`}`);
};
codegen.js(/* js */ `var ${r} = ${value.use()};`);
if (!encodeUnknownFields && !optionalLength) {
this.blob(this.gen((encoder) => encoder.writeObjHdr(length)));
emitRequiredFields();
}
else if (!encodeUnknownFields) {
codegen.js(`var ${rFieldCount} = ${requiredLength};`);
const rHeaderPosition = codegen.var('writer.x');
this.blob(this.gen((encoder) => encoder.writeObjHdr(0xffff)));
emitRequiredFields();
emitOptionalFields();
codegen.js(`view.setUint16(${rHeaderPosition} + 1, ${rFieldCount});`);
}
else {
codegen.js(`var ${rFieldCount} = ${requiredLength};`);
const rHeaderPosition = codegen.var('writer.x');
this.blob(this.gen((encoder) => encoder.writeObjHdr(0xffffffff)));
emitRequiredFields();
emitOptionalFields();
emitUnknownFields();
codegen.js(`view.setUint32(${rHeaderPosition} + 1, ${rFieldCount});`);
}
}
onKey(path, r, type) {
this.onNode([...path, type.key], r, type.val);
}
genEncoder(type) {
return _a.get(type);
}
},
(() => {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_linkGet_decorators = [once_1.once];
tslib_1.__esDecorate(_a, null, _linkGet_decorators, { kind: "method", name: "linkGet", static: false, private: false, access: { has: obj => "linkGet" in obj, get: obj => obj.linkGet }, metadata: _metadata }, null, _instanceExtraInitializers);
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
})(),
_a.get = (0, util_1.lazyKeyedFactory)((type, name) => {
const codegen = new _a(type, name);
const r = codegen.codegen.options.args[0];
const expression = new JsExpression_1.JsExpression(() => r);
codegen.onNode([], expression, type);
return codegen.compile();
}),
_a;
})();
exports.MsgPackCodegen = MsgPackCodegen;
//# sourceMappingURL=MsgPackCodegen.js.map