UNPKG

@jsonjoy.com/json-type

Version:

High-performance JSON Pointer implementation

112 lines (111 loc) 4.44 kB
"use strict"; 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;