86 lines
2.1 KiB
TypeScript
86 lines
2.1 KiB
TypeScript
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 VerbatimOp = WeakCausalTreeOp<PlainTextOperation>;
|
|
type CompressedRun = { st: Timestamp; p: Timestamp | undefined; seq: string };
|
|
|
|
export type CompactedOperations = (VerbatimOp | CompressedRun)[];
|
|
|
|
export function compressOps(ops: CausalTreeOp<PlainTextOperation>[]): CompactedOperations {
|
|
if (ops.length === 0) return [];
|
|
|
|
const runs: CompactedOperations = [];
|
|
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;
|
|
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(
|
|
compacted: CompactedOperations,
|
|
): WeakCausalTreeOp<PlainTextOperation>[] {
|
|
const ops: WeakCausalTreeOp<PlainTextOperation>[] = [];
|
|
|
|
for (const item of compacted) {
|
|
if ("st" in item) {
|
|
let i = 0;
|
|
let parent: Timestamp | undefined = item.p;
|
|
for (const c of item.seq) {
|
|
const op = {
|
|
at: [item.st[0], item.st[1] + i] as Timestamp,
|
|
parent,
|
|
type: "insert",
|
|
sequence: c,
|
|
} as const;
|
|
parent = op.at;
|
|
ops.push(op);
|
|
i++;
|
|
}
|
|
} else {
|
|
ops.push(item);
|
|
}
|
|
}
|
|
|
|
return ops;
|
|
}
|