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 documents 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); ```
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); ```
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.