dal/client/Protocol.ts

110 lines
2.2 KiB
TypeScript
Raw Normal View History

import { encode, decode } from "@msgpack/msgpack";
export interface Method {
method: string;
args: any;
}
export interface Request {
id: number;
db: string;
commands: Method[];
}
export interface ExecResult {
2024-08-21 01:28:40 +00:00
Id: number;
RowsAffected: number;
LastInsertId: number;
Error?: string;
}
2024-08-21 01:28:40 +00:00
export interface Row {
r: unknown[];
}
export type IError = any;
export const METHODS =
2024-08-16 18:10:34 +00:00
"Raw|In|Find|Select|Fields|Join|Group|Sort|Limit|Offset|Delete|Insert|Set|Update|OnConflict|DoUpdate|DoNothing|Tx".split(
"|",
2024-08-21 01:28:40 +00:00
);
export function encodeRequest(request: Request): Uint8Array {
return encode(request);
}
export function decodeResponse(input: Uint8Array): [ExecResult, IError] {
2024-09-02 10:37:34 +00:00
try {
const res = decode(input) as {
i: number;
ra: number;
li: number;
e?: string;
2024-09-02 10:37:34 +00:00
};
const result = {
2024-09-02 10:37:34 +00:00
Id: res.i,
RowsAffected: res.ra,
LastInsertId: res.li,
Error: res.e,
2024-09-02 10:37:34 +00:00
};
return [result, result.Error];
2024-09-02 10:37:34 +00:00
} catch (e) {
return [{} as ExecResult, e];
2024-09-02 10:37:34 +00:00
}
}
const ROW_TAG = [0x81, 0xa1, 0x72];
export function decodeRows(input: Uint8Array): [Row[], IError] {
2024-09-02 10:37:34 +00:00
try {
const rows = [];
let count = 0;
let buf = [];
while (count < input.length) {
if (input.at(count) != 0x81) {
buf.push(input.at(count));
count++;
continue;
}
const [a, b, c] = ROW_TAG;
const [aa, bb, cc] = input.slice(count, count + 4);
if (aa == a && bb == b && cc == c) {
rows.push([...ROW_TAG, ...buf]);
buf = [];
count += 3;
} else {
buf.push(input.at(count));
count++;
}
}
2024-09-02 10:37:34 +00:00
rows.push([...ROW_TAG, ...buf]);
rows.shift();
return [
rows.map((row) => decode(new Uint8Array(row as number[]))) as Row[],
null,
];
2024-09-02 10:37:34 +00:00
} catch (e) {
return [[], e];
}
}
export async function* decodeRowsIterator(
stream: ReadableStream<Uint8Array>,
): AsyncGenerator<[Row, IError]> {
const reader = stream.getReader();
for (;;) {
const { value, done } = await reader.read();
if (done) {
break;
}
const [rows, err] = decodeRows(value);
if (err) {
yield [{} as Row, err];
break;
}
for (const row of rows) {
yield [row, null];
}
}
}