operational-transform

A library for Operational Transformation

Operational transformation (OT) is a technology for supporting a range of collaboration functionalities in advanced collaborative software systems. [1]

When working on the same document over the internet concurrent operations from multiple users might be in conflict. Operational Transform can help to resolve conflicts in such a way that docuemnts stay in sync.

The basic operations that are supported are: - Retain(n): Move the cursor n positions forward - Delete(n): Delete n characters at the current position - Insert(s): Insert the string s at the current position

This library can be used to...

... compose sequences of operations: ```rust use operational_transform::OperationSeq;

let mut a = OperationSeq::default(); a.insert("abc"); let mut b = OperationSeq::default(); b.retain(3); b.insert("def"); let aftera = a.apply("").unwrap(); let afterb = b.apply(&aftera).unwrap(); let c = a.compose(&b).unwrap(); let afterab = a.compose(&b).unwrap().apply("").unwrap(); asserteq!(afterab, after_b); ```

... transform sequences of operations ```rust use operational_transform::OperationSeq;

let s = "abc"; let mut a = OperationSeq::default(); a.retain(3); a.insert("def"); let mut b = OperationSeq::default(); b.retain(3); b.insert("ghi"); let (aprime, bprime) = a.transform(&b).unwrap(); let abprime = a.compose(&bprime).unwrap(); let baprime = b.compose(&aprime).unwrap(); let afterabprime = abprime.apply(s).unwrap(); let afterbaprime = baprime.apply(s).unwrap(); asserteq!(abprime, baprime); asserteq!(afterabprime, afterbaprime); ```

... invert sequences of operations ```rust use operational_transform::OperationSeq;

let s = "abc"; let mut o = OperationSeq::default(); o.retain(3); o.insert("def"); let p = o.invert(s); assert_eq!(p.apply(&o.apply(s).unwrap()).unwrap(), s); ```

Features

Serialisation is supporeted by using the serde feature.

```rust use operationaltransform::OperationSeq; use serdejson;

let o: OperationSeq = serdejson::fromstr("[1,-1,\"abc\"]").unwrap(); let mut oexp = OperationSeq::default(); oexp.retain(1); oexp.delete(1); oexp.insert("abc"); asserteq!(o, oexp); ```

Acknowledgement

In the current state the code is ported from here. It might change in the future as there is much room for optimisation and also usability.