Skip to main content

Crate abyo_crdt

Crate abyo_crdt 

Source
Expand description

§abyo-crdt

Pure Rust CRDT library implementing an Eg-walker-style event log over a Fugue-Maximal list, with companion Map, Counter, and Set CRDTs and Peritext rich text planned for v0.3.

See the README for design background and the crate-level plan for the roadmap.

§Available data types

TypeAlgorithmStatus
List<T>Fugue-Maximalv0.1 ✅
Map<K, V>LWW with Lamportv0.2 ✅
CounterPN-Counterv0.2 ✅
Set<T>OR-Set, add-winsv0.2 ✅
TextPeritextv0.3 🚧

Every CRDT in the crate ships an event log (ops()), supports incremental sync via VersionVector (ops_since(&version)), and is Serialize + Deserialize under the default serde feature.

§Quick start

use abyo_crdt::List;

let mut alice = List::<char>::new(1);
alice.insert(0, 'H');
alice.insert(1, 'i');

let mut bob = List::<char>::new(2);
bob.merge(&alice);

bob.insert(2, '!');
alice.merge(&bob);

assert_eq!(alice.to_vec(), vec!['H', 'i', '!']);
assert_eq!(bob.to_vec(), vec!['H', 'i', '!']);

§Concurrent edits never interleave

Fugue-Maximal guarantees that contiguous bursts of typing stay contiguous after merge, regardless of timing.

use abyo_crdt::List;

let mut alice = List::<char>::new(1);
let mut bob = List::<char>::new(2);

// Both start from a shared "ab" doc
alice.insert(0, 'a');
alice.insert(1, 'b');
bob.merge(&alice);

// Concurrent inserts at position 1 — Alice types "Hello", Bob types "World"
for (i, c) in "Hello".chars().enumerate() {
    alice.insert(1 + i, c);
}
for (i, c) in "World".chars().enumerate() {
    bob.insert(1 + i, c);
}

alice.merge(&bob);
bob.merge(&alice);

let merged: String = alice.iter().collect();
// Either "aHelloWorldb" or "aWorldHellob" — never interleaved.
assert!(merged == "aHelloWorldb" || merged == "aWorldHellob");
assert_eq!(merged, bob.iter().collect::<String>());

Modules§

storage
Storage abstraction for persisting CRDT state across process restarts.
yjs_compat
Wire-format compatibility with Yjs — primitives, state-vector exchange, and a minimal Y.Update v1 snapshot encoder.

Structs§

Counter
PN-Counter CRDT (signed). See the module docs for semantics.
CounterOp
A single Counter CRDT operation.
DeltaOp
One run in a Quill/Yjs Delta — a chunk of text with optional attributes.
List
List CRDT with Fugue-Maximal positioning over an Eg-walker event log.
Map
LWW-Map CRDT. See the module docs for semantics.
MarkSet
Set of marks active at a single character position.
OpId
Globally unique identifier for a single CRDT operation.
Selection
A range selection — two cursors marking the endpoints of a contiguous span.
Set
OR-Set CRDT. See the module docs for semantics.
Span
A format-mark span: applies a named annotation between two anchors.
Text
Rich-text CRDT — a List<char> augmented with Peritext-style format spans.
VersionVector
Summary of “what ops a replica has seen”, indexed by replica.

Enums§

Anchor
A position in the text, expressed relative to a specific character or the document boundaries.
AnchorSide
Which side of an anchored character the anchor sits on.
AttrValue
Value of a single attribute in a Quill/Yjs Delta operation.
Cursor
A position in a List that follows concurrent edits.
CursorSide
Which side of the anchored character the cursor sits on.
Error
Errors that can occur in abyo-crdt.
ExpandRule
Stickiness rule for mark anchors.
ListOp
A single List CRDT operation. Wire-format and event-log entry.
MapOp
A single Map CRDT operation.
MarkValue
What a mark currently “is” at a character position.
SetOp
A single Set CRDT operation.
Side
Side of a parent that an item is anchored to in the Fugue tree.
SpanValue
The “value” carried by a format span — boolean on/off for marks like bold/italic, or a string value for marks like href/color.
TextOp
A single text-CRDT operation.

Functions§

new_replica_id
Generate a random ReplicaId from OS entropy.

Type Aliases§

ReplicaId
Identifier for a replica (collaborator).