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