Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
Publish MCP to npm / Build, test, and publish MCP (push) Waiting to run
Publish SDK to npm / Build, test, and publish SDK (push) Waiting to run
Sync action catalog to docs / sync (push) Waiting to run
Publish UI to npm / Build and publish UI (push) Waiting to run
Build and Release / preflight (push) Waiting to run
69 lines
1.9 KiB
TypeScript
69 lines
1.9 KiB
TypeScript
// Independent protobuf byte-oracle helpers for OIDB service tests.
|
|
//
|
|
// These build expected wire bytes from FIRST PRINCIPLES (the RE'd tag
|
|
// numbers), NOT via proton — so asserting `proton.encode(...) === pb.env(...)`
|
|
// goes red if a proto-defs field tag is wrong or silently changes. A
|
|
// symmetric encode→decode round-trip can't catch a tag swap; this can.
|
|
//
|
|
// Emission rules mirror proton's observed behaviour: fields in ASCENDING
|
|
// tag order, and proto3 defaults (0 / '' / false) OMITTED.
|
|
|
|
function uvarint(n: number): number[] {
|
|
const out: number[] = [];
|
|
let x = n;
|
|
|
|
do {
|
|
let b = x % 128;
|
|
x = Math.floor(x / 128);
|
|
|
|
if (x > 0) {
|
|
b |= 0x80;
|
|
}
|
|
|
|
out.push(b);
|
|
} while (x > 0);
|
|
|
|
return out;
|
|
}
|
|
|
|
function tag(field: number, wire: number): number[] {
|
|
return uvarint(field * 8 + wire);
|
|
}
|
|
|
|
/** varint field (wire type 0). */
|
|
export function v(field: number, value: number): number[] {
|
|
return [...tag(field, 0), ...uvarint(value)];
|
|
}
|
|
|
|
/** length-delimited string field (wire type 2). */
|
|
export function s(field: number, str: string): number[] {
|
|
const b = [...Buffer.from(str, 'utf8')];
|
|
return [...tag(field, 2), ...uvarint(b.length), ...b];
|
|
}
|
|
|
|
/** length-delimited sub-message field (wire type 2). */
|
|
export function m(field: number, msg: number[]): number[] {
|
|
return [...tag(field, 2), ...uvarint(msg.length), ...msg];
|
|
}
|
|
|
|
/**
|
|
* Wrap a body in the OidbBase envelope exactly as proton emits it:
|
|
* command(1), subCommand(2) [omitted when 0], body(4), reserved(12)=1
|
|
* [only when uinForm]. errorCode(3)/errorMsg(5) are defaults → omitted.
|
|
*/
|
|
export function env(command: number, subCommand: number, body: number[], uinForm: boolean): string {
|
|
const out = [...v(1, command)];
|
|
|
|
if (subCommand !== 0) {
|
|
out.push(...v(2, subCommand));
|
|
}
|
|
|
|
out.push(...m(4, body));
|
|
|
|
if (uinForm) {
|
|
out.push(...v(12, 1));
|
|
}
|
|
|
|
return Buffer.from(out).toString('hex');
|
|
}
|