2024-08-15 13:04:44 +00:00
|
|
|
import { encode, decode } from "@msgpack/msgpack";
|
2024-08-15 08:19:50 +00:00
|
|
|
|
|
|
|
export interface Method {
|
2024-08-15 13:04:44 +00:00
|
|
|
method: string;
|
|
|
|
args: any;
|
2024-08-15 08:19:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface Request {
|
2024-08-15 13:04:44 +00:00
|
|
|
id: number;
|
|
|
|
db: string;
|
|
|
|
commands: Method[];
|
2024-08-15 08:19:50 +00:00
|
|
|
}
|
|
|
|
|
2024-08-16 04:18:45 +00:00
|
|
|
export interface ExecResult {
|
2024-08-21 01:28:40 +00:00
|
|
|
Id: number;
|
|
|
|
RowsAffected: number;
|
|
|
|
LastInsertId: number;
|
|
|
|
Msg?: string;
|
2024-08-16 04:18:45 +00:00
|
|
|
}
|
|
|
|
|
2024-08-21 01:28:40 +00:00
|
|
|
export interface Row {
|
2024-08-16 04:18:45 +00:00
|
|
|
r: unknown[];
|
|
|
|
}
|
|
|
|
|
2024-08-15 13:04:44 +00:00
|
|
|
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-15 13:04:44 +00:00
|
|
|
"|",
|
2024-08-21 01:28:40 +00:00
|
|
|
);
|
2024-08-15 08:19:50 +00:00
|
|
|
|
|
|
|
export function encodeRequest(request: Request): Uint8Array {
|
2024-08-15 13:04:44 +00:00
|
|
|
return encode(request);
|
2024-08-15 11:31:56 +00:00
|
|
|
}
|
|
|
|
|
2024-08-16 04:18:45 +00:00
|
|
|
export function decodeResponse(input: Uint8Array): ExecResult {
|
2024-08-21 01:28:40 +00:00
|
|
|
const res = decode(input) as {
|
|
|
|
i: number;
|
|
|
|
ra: number;
|
|
|
|
li: number;
|
|
|
|
m?: string;
|
|
|
|
};
|
|
|
|
return {
|
|
|
|
Id: res.i,
|
|
|
|
RowsAffected: res.ra,
|
|
|
|
LastInsertId: res.li,
|
|
|
|
Msg: res.m,
|
|
|
|
};
|
2024-08-15 11:31:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const ROW_TAG = [0x81, 0xa1, 0x72];
|
|
|
|
|
|
|
|
export function decodeRows(input: Uint8Array): Row[] {
|
2024-08-15 13:04:44 +00:00
|
|
|
const rows = [];
|
|
|
|
let count = 0;
|
|
|
|
let buf = [];
|
|
|
|
while (count < input.length) {
|
|
|
|
if (input.at(count) != 0x81) {
|
|
|
|
buf.push(input.at(count));
|
|
|
|
count++;
|
|
|
|
continue;
|
2024-08-15 11:31:56 +00:00
|
|
|
}
|
2024-08-15 13:04:44 +00:00
|
|
|
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++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rows.push([...ROW_TAG, ...buf]);
|
|
|
|
rows.shift();
|
|
|
|
return rows.map((row) => decode(new Uint8Array(row as number[]))) as Row[];
|
2024-08-15 11:31:56 +00:00
|
|
|
}
|
|
|
|
|
2024-08-15 13:04:44 +00:00
|
|
|
export async function* decodeRowsIterator(
|
|
|
|
stream: ReadableStream<Uint8Array>,
|
|
|
|
): AsyncGenerator<Row> {
|
|
|
|
const reader = stream.getReader();
|
|
|
|
for (;;) {
|
|
|
|
const { value, done } = await reader.read();
|
|
|
|
if (done) {
|
|
|
|
break;
|
|
|
|
}
|
2024-08-22 18:03:46 +00:00
|
|
|
const rows = decodeRows(value);
|
2024-08-15 13:04:44 +00:00
|
|
|
for (const row of rows) {
|
|
|
|
yield row;
|
2024-08-15 11:31:56 +00:00
|
|
|
}
|
2024-08-15 13:04:44 +00:00
|
|
|
}
|
|
|
|
}
|