@jsonjoy.com/json-type
Version:
High-performance JSON Pointer implementation
112 lines (111 loc) • 4.44 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BinaryEncoderCodegenContext = void 0;
const codegen_1 = require("@jsonjoy.com/util/lib/codegen");
const WriteBlobStep_1 = require("../WriteBlobStep");
const concat_1 = require("@jsonjoy.com/util/lib/buffers/concat");
const Value_1 = require("../../value/Value");
class BinaryEncoderCodegenContext {
constructor(options) {
this.options = options;
this.codegen = new codegen_1.Codegen({
name: 'toBinary' + (options.name ? '_' + options.name : ''),
args: ['r0', 'encoder'],
prologue: /* js */ `
var writer = encoder.writer;
writer.ensureCapacity(capacityEstimator(r0));
var uint8 = writer.uint8, view = writer.view;`,
epilogue: '',
linkable: {
Value: Value_1.Value,
},
processSteps: (steps) => {
const stepsJoined = [];
for (let i = 0; i < steps.length; i++) {
const step = steps[i];
if (step instanceof codegen_1.CodegenStepExecJs)
stepsJoined.push(step);
else if (step instanceof WriteBlobStep_1.WriteBlobStep) {
const last = stepsJoined[stepsJoined.length - 1];
if (last instanceof WriteBlobStep_1.WriteBlobStep)
last.arr = (0, concat_1.concat)(last.arr, step.arr);
else
stepsJoined.push(step);
}
}
const execSteps = [];
for (const step of stepsJoined) {
if (step instanceof codegen_1.CodegenStepExecJs) {
execSteps.push(step);
}
else if (step instanceof WriteBlobStep_1.WriteBlobStep) {
execSteps.push(this.codegenBlob(step));
}
}
return execSteps;
},
});
this.codegen.linkDependency(options.type.capacityEstimator(), 'capacityEstimator');
}
getBigIntStr(arr, offset) {
const buf = new Uint8Array(8);
for (let i = 0; i < 8; i++)
buf[i] = arr[offset + i];
const view = new DataView(buf.buffer);
const bigint = view.getBigUint64(0);
return bigint.toString() + 'n';
}
codegenBlob(step) {
const lines = [];
const ro = this.codegen.getRegister();
const length = step.arr.length;
if (length === 1) {
lines.push(/* js */ `uint8[writer.x++] = ${step.arr[0]};`);
}
else {
lines.push(`var ${ro} = writer.x;`);
lines.push(`writer.x += ${step.arr.length};`);
let i = 0;
while (i < length) {
const remaining = length - i;
if (remaining >= 8) {
const value = this.getBigIntStr(step.arr, i);
lines.push(/* js */ `view.setBigUint64(${ro}${i ? ` + ${i}` : ''}, ${value});`);
i += 8;
}
else if (remaining >= 4) {
const value = (step.arr[i] << 24) | (step.arr[i + 1] << 16) | (step.arr[i + 2] << 8) | step.arr[i + 3];
lines.push(/* js */ `view.setInt32(${ro}${i ? ` + ${i}` : ''}, ${value});`);
i += 4;
}
else if (remaining >= 2) {
const value = (step.arr[i] << 8) | step.arr[i + 1];
lines.push(/* js */ `view.setInt16(${ro}${i ? ` + ${i}` : ''}, ${value});`);
i += 2;
}
else {
lines.push(/* js */ `uint8[${ro}${i ? ` + ${i}` : ''}] = ${step.arr[i]};`);
i++;
}
}
}
const js = lines.join('\n');
return new codegen_1.CodegenStepExecJs(js);
}
js(js) {
this.codegen.js(js);
}
gen(callback) {
const { encoder } = this.options;
encoder.writer.reset();
callback(encoder);
return encoder.writer.flush();
}
blob(arr) {
this.codegen.step(new WriteBlobStep_1.WriteBlobStep(arr));
}
compile() {
return this.codegen.compile();
}
}
exports.BinaryEncoderCodegenContext = BinaryEncoderCodegenContext;