JSFiddle - React, Tailwind, and code Playground
by Yaroslav Samardak
TypeScript
import { Parser } from "binary-parser"
import { Buffer } from "buffer"
type FieldDef = {
id: string
type: 'int16' | 'uint16' | 'int32' | 'uint32'
}
type ComposeOp = {
id: string
op: 'compose'
mode: 'bitwise'
inputs: string[]
width: number
signed: boolean
}
type Schema = {
fields: FieldDef[] // порядок = порядок в бинаре
operations: ComposeOp[]
output: string[]
}
const TYPE_WIDTH: Record<string, number> = {
int8: 8,
uint8: 8,
int16: 16,
uint16: 16,
int32: 32,
uint32: 32
}
function composeBitwise(
inputs: string[],
ctx: any,
fieldById: Record<string, FieldDef>,
totalWidth: number,
signed: boolean
): number {
let result = 0
let shift = totalWidth
for (const id of inputs) {
const field = fieldById[id]
if (!field) {
throw new Error(`Unknown field "${id}" in compose`)
}
const width = TYPE_WIDTH[field.type]
const value = ctx[id]
shift -= width
result |= (value & ((1 << width) - 1)) << shift
}
if (signed) {
const signBit = 1 << (totalWidth - 1)
if (result & signBit) {
result -= 1 << totalWidth
}
}
return result
}
function buildFormatter(schema: Schema) {
const fieldById = Object.fromEntries(
schema.fields.map(f => [f.id, f])
)
return function formatter(raw: any) {
const ctx: any = { ...raw }
for (const op of schema.operations) {
if (op.op === 'compose' && op.mode === 'bitwise') {
ctx[op.id] = composeBitwise(
op.inputs,
ctx,
fieldById,
op.width,
op.signed
)
}
}
const result: any = {}
for (const key of schema.output) {
result[key] = ctx[key]
}
return result
}
}
function buildParser(schema: Schema): Parser {
let parser = new Parser()
for (const field of schema.fields) {
parser = (parser as...