oficina / docs Public

Clone
git clone https://amadan.net/oficina/docs

Plain git — no account needed to clone.

Download

Download this file

1# Yrs
2
3Yrs (read: *wires*) is a Rust port of the [Yjs framework](https://yjs.dev/).
4
5It's a library used on collaborative document editing using Conflict-free Replicated Data Types.
6This enables to provide a shared document editing experience on a client devices without explicit requirement for hosting a single server - CRDTs can resolve potential update conflicts on their own with no central authority - as well as provide first-class offline editing capabilities, where document replicas are modified without having connection to each other, and then synchronize automatically once such connection is enabled.
7
8This library contains Rust API, that's used further on by other projects in this repository:
9
10- [C foreign function interface](https://github.com/y-crdt/y-crdt/tree/main/yffi) to provide native interop that could be used by other host languages like Swift or Java.
11- [ywasm](https://github.com/y-crdt/y-crdt/tree/main/ywasm) which targets Web Assembly bindings and can be used directly from JavaScript.
12
13## Example
14
15```rust
16use yrs::*;
17
18fn main() {
19 let doc = Doc::new();
20 let text = doc.get_or_insert_text("name");
21 // every operation in Yrs happens in scope of a transaction
22 let mut txn = doc.transact_mut();
23 // append text to our collaborative document
24 text.push(&mut txn, "Hello from yrs!");
25 // add formatting section to part of the text
26 text.format(&mut txn, 11, 3, HashMap::from([
27 ("link".into(), "https://github.com/y-crdt/y-crdt".into())
28 ]));
29
30 // simulate update with remote peer
31 let remote_doc = Doc::new();
32 let remote_text = remote_doc.get_or_insert_text("name");
33 let mut remote_txn = remote_doc.transact_mut();
34
35 // in order to exchange data with other documents
36 // we first need to create a state vector
37 let state_vector = remote_txn.state_vector();
38
39 // now compute a differential update based on remote document's
40 // state vector
41 let bytes = txn.encode_diff_v1(&state_vector);
42
43 // both update and state vector are serializable, we can pass them
44 // over the wire now apply update to a remote document
45 let update = Update::decode_v1(&bytes).unwrap();
46 remote_txn.apply_update(update);
47
48 // display raw text (no attributes)
49 println!("{}", remote_text.get_string(&remote_txn));
50
51 // create sequence of text chunks with optional format attributes
52 let diff = remote_text.diff(&remote_txn, YChange::identity);
53}
54```
55
56## [Documentation](https://docs.rs/yrs/)
57
58## Features
59
60We're in ongoing process of reaching the feature compatibility with Yjs project. Current feature list:
61
62- [x] Yjs update binary format (v1).
63- [x] Yjs update binary format (v2).
64- [x] Support for state vectors, delta diff updates and merges.
65- [x] Subscription events for incoming updates.
66- [x] Support for shared (CRDT) types:
67 - [x] Text
68 - [x] Array
69 - [x] Map
70 - [x] XML data types (XmlFragment, XmlElement, XmlText, XmlHook)
71 - [x] Subdocuments
72 - [x] Subscription events on particular data type
73- [x] Cross-platform support for unicode code points
74- [x] Transaction origins
75- [x] Undo manager
76
77## Internal Documentation
78
79Yrs implements the same algorithm and uses the same data structures as Yjs. We
80hope to achieve better performance because we can manually manage memory.
81Eventually Yrs might replace the Yjs module by generating a wasm module from
82this package.
83
84In this package we want to use better terminology and experiment with new data
85structures to index data.
86
87Each change on the document generates a small piece of information that is
88integrated into the document. In Yrs we call these small pieces **blocks**.
89Think of them as small Lego blocks that compose your document. Each block is
90uniquely identified by an identifier consisting of client id and sequence number
91(see: [Lamport Clock](https://en.wikipedia.org/wiki/Lamport_timestamp)).
92When you receive a duplicate block, you discard it. In some cases blocks can be put
93together to form a larger block. If necessary, blocks can be disassembled if only
94a part of the composed block is needed.
95
96More information on the implemented algorithm can be found here:
97
98* [Paper describing the YATA conflict resolution algorithm](https://www.researchgate.net/publication/310212186_Near_Real-Time_Peer-to-Peer_Shared_Editing_on_Extensible_Data_Types)
99* [Short overview of the Yjs optimizations](https://github.com/yjs/yjs/blob/main/README.md#yjs-crdt-algorithm)
100* [Motivation for composable blocks](https://blog.kevinjahns.de/are-crdts-suitable-for-shared-editing/)
101* [Internal documentation of the Yjs project](https://github.com/yjs/yjs/blob/main/INTERNALS.md)
102* [Walkthrough of the Yjs codebase](https://youtu.be/0l5XgnQ6rB4)
103