Operational transformation for collaborative editing (Tier 3, T3.1).
Ops address glyphs by opaque seq-based UID, which a text edit renumbers. OT
works instead in a stable address space Addr{contents_ref, op_index, glyph_idx}: op_index never shifts (edits preserve the show-op count) and
glyph_idx shifts only within a run that lost an earlier glyph. So
different-run edits commute and the transform only handles same-run cases.
Summary
Functions
Resolves a glyph uid to its stable Addr (immune to the seq-based UID renumbering a text edit causes).
Resolves a Pending back to a concrete PdfEx.Op against the current document.
Builds a Pending op in stable-address space from op, tagged with the base_version it was built against.
Resolves a stable Addr back to the current glyph uid in doc.
Transforms b to apply after the already-applied concurrent a (same base).
Returns :noop when b's intent is subsumed. See the spec's locked matrix.
Folds transform/2 over the applied concurrent ops; short-circuits to :noop if any transform drops pending.
Functions
@spec address(PdfEx.Document.t(), binary()) :: {:ok, PdfEx.OT.Addr.t()} | {:error, PdfEx.Error.t()}
Resolves a glyph uid to its stable Addr (immune to the seq-based UID renumbering a text edit causes).
@spec materialize(PdfEx.Document.t(), PdfEx.OT.Pending.t()) :: {:ok, PdfEx.Op.t()} | {:error, PdfEx.Error.t()}
Resolves a Pending back to a concrete PdfEx.Op against the current document.
@spec pending(PdfEx.Document.t(), PdfEx.Op.t(), non_neg_integer()) :: {:ok, PdfEx.OT.Pending.t()} | {:error, PdfEx.Error.t()}
Builds a Pending op in stable-address space from op, tagged with the base_version it was built against.
@spec resolve(PdfEx.Document.t(), PdfEx.OT.Addr.t()) :: {:ok, binary()} | {:error, PdfEx.Error.t()}
Resolves a stable Addr back to the current glyph uid in doc.
@spec transform(PdfEx.OT.Pending.t(), PdfEx.OT.Pending.t()) :: {:ok, PdfEx.OT.Pending.t()} | :noop
Transforms b to apply after the already-applied concurrent a (same base).
Returns :noop when b's intent is subsumed. See the spec's locked matrix.
@spec transform_against(PdfEx.OT.Pending.t(), [PdfEx.OT.Pending.t()]) :: {:ok, PdfEx.OT.Pending.t()} | :noop
Folds transform/2 over the applied concurrent ops; short-circuits to :noop if any transform drops pending.