add compaction for the wire protocol
this batches contiguous runs of characters from a host into a single object
This commit is contained in:
parent
2c1cfbc701
commit
76541aea85
2 changed files with 86 additions and 0 deletions
81
compression.ts
Normal file
81
compression.ts
Normal file
|
@ -0,0 +1,81 @@
|
|||
import { Timestamp } from "./sync/common.ts";
|
||||
import { CausalTree, CausalTreeOp, WeakCausalTreeOp } from "./sync/ordt/causal-tree.ts";
|
||||
import { PlainTextOperation } from "./sync/ordt/plain-text.ts";
|
||||
|
||||
type VerbatimRun = WeakCausalTreeOp<PlainTextOperation>;
|
||||
type CompressedRun = { st: Timestamp; p: Timestamp | undefined; seq: string };
|
||||
type Run = VerbatimRun | CompressedRun;
|
||||
|
||||
export function compressOps(ops: CausalTreeOp<PlainTextOperation>[]): Run[] {
|
||||
if (ops.length === 0) throw new Error("can't create a compressed run!");
|
||||
|
||||
const runs: Run[] = [];
|
||||
let seq = "";
|
||||
let cnt = 0;
|
||||
let start: Timestamp | undefined;
|
||||
let firstParent: Timestamp | undefined;
|
||||
for (let i = 0; i < ops.length; i++) {
|
||||
const op = ops[i];
|
||||
const lastOp = ops[i - 1];
|
||||
|
||||
if (!start) start = op.at;
|
||||
if (!firstParent) firstParent = op.parent?.at;
|
||||
|
||||
if (
|
||||
op.type === "insert" &&
|
||||
op.sequence.length === 1 &&
|
||||
(cnt === 0 ||
|
||||
(op.parent?.at?.[0] === lastOp.at[0] &&
|
||||
op.parent?.at?.[1] === lastOp.at[1] &&
|
||||
op.at[0] === lastOp.at[0] &&
|
||||
op.at[1] === lastOp.at[1] + 1))
|
||||
) {
|
||||
seq += op.sequence;
|
||||
cnt++;
|
||||
} else {
|
||||
if (cnt > 0) {
|
||||
runs.push({ st: start!, p: firstParent, seq });
|
||||
i--;
|
||||
} else {
|
||||
runs.push(CausalTree.toWeakOp(op));
|
||||
}
|
||||
|
||||
start = undefined;
|
||||
firstParent = undefined;
|
||||
seq = "";
|
||||
cnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (cnt > 1) {
|
||||
runs.push({ st: start!, p: firstParent, seq });
|
||||
}
|
||||
|
||||
return runs;
|
||||
}
|
||||
|
||||
export function decompressOps(runs: Run[]): WeakCausalTreeOp<PlainTextOperation>[] {
|
||||
const ops: WeakCausalTreeOp<PlainTextOperation>[] = [];
|
||||
|
||||
for (const run of runs) {
|
||||
if ("st" in run) {
|
||||
let i = 0;
|
||||
let parent: Timestamp | undefined = run.p;
|
||||
for (const c of run.seq) {
|
||||
const op = {
|
||||
at: [run.st[0], run.st[1] + i] as Timestamp,
|
||||
parent,
|
||||
type: "insert",
|
||||
sequence: c,
|
||||
} as const;
|
||||
parent = op.at;
|
||||
ops.push(op);
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
ops.push(run);
|
||||
}
|
||||
}
|
||||
|
||||
return ops;
|
||||
}
|
|
@ -1,5 +1,10 @@
|
|||
{
|
||||
"version": "0.1.0",
|
||||
"tasks": {
|
||||
"build": "deno run -A ./_build.ts",
|
||||
"watch": "deno run -A ./_build.ts --watch",
|
||||
"serve": "deno run -A ./server.ts"
|
||||
},
|
||||
"imports": {
|
||||
"@char/aftercare": "jsr:@char/aftercare@^0.3.0",
|
||||
"@oak/oak": "jsr:@oak/oak@^17.1.4"
|
||||
|
|
Loading…
Reference in a new issue