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; type CompressedRun = { st: Timestamp; p: Timestamp | undefined; seq: string }; type Run = VerbatimRun | CompressedRun; export function compressOps(ops: CausalTreeOp[]): 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[] { const ops: WeakCausalTreeOp[] = []; 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; }