oficina / docs Public

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

Plain git — no account needed to clone.

Download

Download this file

1use crate::block::ClientID;
2use crate::encoding::varint::Signed;
3use crate::encoding::write::Write;
4use crate::*;
5use std::collections::HashMap;
6
7/// A trait that can be implemented by any other type in order to support lib0 encoding capability.
8pub trait Encode {
9 fn encode<E: Encoder>(&self, encoder: &mut E);
10
11 /// Helper function for encoding 1st version of lib0 encoding.
12 fn encode_v1(&self) -> Vec<u8> {
13 let mut encoder = EncoderV1::new();
14 self.encode(&mut encoder);
15 encoder.to_vec()
16 }
17
18 /// Helper function for encoding 2nd version of lib0 encoding.
19 fn encode_v2(&self) -> Vec<u8> {
20 let mut encoder = EncoderV2::new();
21 self.encode(&mut encoder);
22 encoder.to_vec()
23 }
24}
25
26/// Trait used by lib0 encoders. Natively lib0 encoding supports two versions:
27///
28/// 1. 1st version (implemented in Yrs) uses simple optimization techniques like var int encoding.
29/// 2. 2nd version optimizes bigger batches of blocks by using run-length encoding.
30///
31/// Both of these define a common set of operations defined in this trait.
32pub trait Encoder: Write {
33 /// Consume current encoder and return a binary with all data encoded so far.
34 fn to_vec(self) -> Vec<u8>;
35
36 /// Reset the state of currently encoded [DeleteSet].
37 fn reset_ds_cur_val(&mut self);
38
39 /// Write a clock value of currently encoded [DeleteSet] client.
40 fn write_ds_clock(&mut self, clock: u32);
41
42 /// Write a number of client entries used by currently encoded [DeleteSet].
43 fn write_ds_len(&mut self, len: u32);
44
45 /// Write unique identifier of a currently encoded [Block]'s left origin.
46 fn write_left_id(&mut self, id: &block::ID);
47
48 /// Write unique identifier of a currently encoded [Block]'s right origin.
49 fn write_right_id(&mut self, id: &block::ID);
50
51 /// Write currently encoded client identifier.
52 fn write_client(&mut self, client: ClientID);
53
54 /// Write currently encoded [Block]'s info flags. These contain information about which fields
55 /// have been provided and which should be skipped during decoding process as well as a type of
56 /// block currently encoded.
57 fn write_info(&mut self, info: u8);
58
59 /// Write info flag about currently encoded [Block]'s parent. Is is another block or root type.
60 fn write_parent_info(&mut self, is_y_key: bool);
61
62 /// Writes type ref data of currently encoded [Block]'s parent.
63 fn write_type_ref(&mut self, info: u8);
64
65 /// Write length parameter.
66 fn write_len(&mut self, len: u32);
67
68 /// Encode JSON-like data type. This is a complex structure which is an extension to JavaScript
69 /// Object Notation with some extra cases.
70 fn write_any(&mut self, any: &Any);
71
72 /// Encode JSON-like data type as nested JSON string. This is a complex structure which is an
73 /// extension to JavaScript Object Notation with some extra cases.
74 fn write_json(&mut self, any: &Any);
75
76 /// Write a string key.
77 fn write_key(&mut self, string: &str);
78}
79
80pub struct EncoderV1 {
81 buf: Vec<u8>,
82}
83
84impl EncoderV1 {
85 pub fn new() -> Self {
86 EncoderV1 {
87 buf: Vec::with_capacity(1024),
88 }
89 }
90
91 fn write_id(&mut self, id: &ID) {
92 self.write_var(id.client);
93 self.write_var(id.clock)
94 }
95}
96
97impl Write for EncoderV1 {
98 #[inline]
99 fn write_all(&mut self, buf: &[u8]) {
100 self.buf.write_all(buf)
101 }
102
103 #[inline]
104 fn write_u8(&mut self, value: u8) {
105 self.buf.write_u8(value)
106 }
107}
108
109impl Encoder for EncoderV1 {
110 #[inline]
111 fn to_vec(self) -> Vec<u8> {
112 self.buf
113 }
114
115 #[inline]
116 fn reset_ds_cur_val(&mut self) {
117 /* no op */
118 }
119
120 #[inline]
121 fn write_ds_clock(&mut self, clock: u32) {
122 self.write_var(clock)
123 }
124
125 #[inline]
126 fn write_ds_len(&mut self, len: u32) {
127 self.write_var(len)
128 }
129
130 #[inline]
131 fn write_left_id(&mut self, id: &ID) {
132 self.write_id(id)
133 }
134
135 #[inline]
136 fn write_right_id(&mut self, id: &ID) {
137 self.write_id(id)
138 }
139
140 #[inline]
141 fn write_client(&mut self, client: ClientID) {
142 self.write_var(client)
143 }
144
145 #[inline]
146 fn write_info(&mut self, info: u8) {
147 self.write_u8(info)
148 }
149
150 #[inline]
151 fn write_parent_info(&mut self, is_y_key: bool) {
152 self.write_var(if is_y_key { 1 as u32 } else { 0 as u32 })
153 }
154
155 #[inline]
156 fn write_type_ref(&mut self, info: u8) {
157 self.write_u8(info)
158 }
159
160 #[inline]
161 fn write_len(&mut self, len: u32) {
162 self.write_var(len)
163 }
164
165 #[inline]
166 fn write_any(&mut self, any: &Any) {
167 any.encode(self)
168 }
169
170 fn write_json(&mut self, any: &Any) {
171 let mut buf = String::new();
172 any.to_json(&mut buf);
173 self.write_string(buf.as_str())
174 }
175
176 #[inline]
177 fn write_key(&mut self, key: &str) {
178 self.write_string(key)
179 }
180}
181
182pub struct EncoderV2 {
183 key_table: HashMap<String, u32>,
184 buf: Vec<u8>,
185 ds_curr_val: u32,
186 seqeuncer: u32,
187 key_clock_encoder: IntDiffOptRleEncoder,
188 client_encoder: UIntOptRleEncoder,
189 left_clock_encoder: IntDiffOptRleEncoder,
190 right_clock_encoder: IntDiffOptRleEncoder,
191 info_encoder: RleEncoder,
192 string_encoder: StringEncoder,
193 parent_info_encoder: RleEncoder,
194 type_ref_encoder: UIntOptRleEncoder,
195 len_encoder: UIntOptRleEncoder,
196}
197
198impl EncoderV2 {
199 pub fn new() -> Self {
200 EncoderV2 {
201 key_table: HashMap::new(),
202 buf: Vec::new(),
203 seqeuncer: 0,
204 ds_curr_val: 0,
205 key_clock_encoder: IntDiffOptRleEncoder::new(),
206 client_encoder: UIntOptRleEncoder::new(),
207 left_clock_encoder: IntDiffOptRleEncoder::new(),
208 right_clock_encoder: IntDiffOptRleEncoder::new(),
209 info_encoder: RleEncoder::new(),
210 string_encoder: StringEncoder::new(),
211 parent_info_encoder: RleEncoder::new(),
212 type_ref_encoder: UIntOptRleEncoder::new(),
213 len_encoder: UIntOptRleEncoder::new(),
214 }
215 }
216}
217
218impl Write for EncoderV2 {
219 #[inline]
220 fn write_all(&mut self, buf: &[u8]) {
221 self.buf.write_buf(buf)
222 }
223
224 #[inline]
225 fn write_u8(&mut self, value: u8) {
226 self.buf.write_u8(value)
227 }
228
229 #[inline]
230 fn write_string(&mut self, str: &str) {
231 self.string_encoder.write(str)
232 }
233}
234
235impl Encoder for EncoderV2 {
236 fn to_vec(self) -> Vec<u8> {
237 let key_clock = self.key_clock_encoder.to_vec();
238 let client = self.client_encoder.to_vec();
239 let left_clock = self.left_clock_encoder.to_vec();
240 let right_clock = self.right_clock_encoder.to_vec();
241 let info = self.info_encoder.to_vec();
242 let string = self.string_encoder.to_vec();
243 let parent_info = self.parent_info_encoder.to_vec();
244 let type_ref = self.type_ref_encoder.to_vec();
245 let len = self.len_encoder.to_vec();
246 let rest = self.buf;
247 let mut buf = Vec::new();
248 buf.write_u8(0); // this is a feature flag that we might use in the future
249 buf.write_buf(key_clock);
250 buf.write_buf(client);
251 buf.write_buf(left_clock);
252 buf.write_buf(right_clock);
253 buf.write_buf(info);
254 buf.write_buf(string);
255 buf.write_buf(parent_info);
256 buf.write_buf(type_ref);
257 buf.write_buf(len);
258 buf.write_all(rest.as_slice());
259 buf
260 }
261
262 #[inline]
263 fn reset_ds_cur_val(&mut self) {
264 self.ds_curr_val = 0;
265 }
266
267 fn write_ds_clock(&mut self, clock: u32) {
268 let diff = clock - self.ds_curr_val;
269 self.ds_curr_val = clock;
270 self.buf.write_var(diff)
271 }
272
273 fn write_ds_len(&mut self, len: u32) {
274 debug_assert!(len != 0);
275 self.buf.write_var(len - 1);
276 self.ds_curr_val += len;
277 }
278
279 fn write_left_id(&mut self, id: &ID) {
280 self.client_encoder.write_u64(id.client as u64);
281 self.left_clock_encoder.write_u32(id.clock)
282 }
283
284 fn write_right_id(&mut self, id: &ID) {
285 self.client_encoder.write_u64(id.client as u64);
286 self.right_clock_encoder.write_u32(id.clock)
287 }
288
289 #[inline]
290 fn write_client(&mut self, client: ClientID) {
291 self.client_encoder.write_u64(client as u64)
292 }
293
294 #[inline]
295 fn write_info(&mut self, info: u8) {
296 self.info_encoder.write_u8(info)
297 }
298
299 #[inline]
300 fn write_parent_info(&mut self, is_y_key: bool) {
301 self.parent_info_encoder
302 .write_u8(if is_y_key { 1 } else { 0 })
303 }
304
305 #[inline]
306 fn write_type_ref(&mut self, info: u8) {
307 self.type_ref_encoder.write_u64(info as u64)
308 }
309
310 #[inline]
311 fn write_len(&mut self, len: u32) {
312 self.len_encoder.write_u64(len as u64);
313 }
314
315 #[inline]
316 fn write_any(&mut self, any: &Any) {
317 let mut encoder = EncoderV1 {
318 buf: std::mem::take(&mut self.buf),
319 };
320 any.encode(&mut encoder);
321 self.buf = encoder.buf;
322 }
323
324 fn write_json(&mut self, any: &Any) {
325 self.write_any(any)
326 }
327
328 fn write_key(&mut self, key: &str) {
329 //TODO: this is wrong (key_table is never updated), but this behavior matches Yjs
330 self.key_clock_encoder.write_u32(self.seqeuncer);
331 self.seqeuncer += 1;
332 if self.key_table.get(key).is_none() {
333 self.string_encoder.write(key);
334 }
335 }
336}
337
338/// A combination of the IntDiffEncoder and the UintOptRleEncoder.
339///
340/// The count approach is similar to the UintDiffOptRleEncoder, but instead of using the negative bitflag, it encodes
341/// in the LSB whether a count is to be read. Therefore this Encoder only supports 31 bit integers!
342///
343/// Encodes [1, 2, 3, 2] as [3, 1, 6, -1] (more specifically [(1 << 1) | 1, (3 << 0) | 0, -1])
344///
345/// Internally uses variable length encoding. Contrary to normal UintVar encoding, the first byte contains:
346/// * 1 bit that denotes whether the next value is a count (LSB)
347/// * 1 bit that denotes whether this value is negative (MSB - 1)
348/// * 1 bit that denotes whether to continue reading the variable length integer (MSB)
349///
350/// Therefore, only five bits remain to encode diff ranges.
351///
352/// Use this Encoder only when appropriate. In most cases, this is probably a bad idea.
353struct IntDiffOptRleEncoder {
354 buf: Vec<u8>,
355 last: u32,
356 count: u32,
357 diff: i32,
358}
359
360impl IntDiffOptRleEncoder {
361 fn new() -> Self {
362 IntDiffOptRleEncoder {
363 buf: Vec::new(),
364 last: 0,
365 count: 0,
366 diff: 0,
367 }
368 }
369
370 fn write_u32(&mut self, value: u32) {
371 let diff = value as i32 - self.last as i32;
372 if self.diff == diff {
373 self.last = value;
374 self.count += 1;
375 } else {
376 self.flush();
377 self.count = 1;
378 self.diff = diff;
379 self.last = value;
380 }
381 }
382
383 fn flush(&mut self) {
384 if self.count > 0 {
385 // 31 bit making up the diff | wether to write the counter
386 let encode_diff = self.diff << 1 | (if self.count == 1 { 0 } else { 1 });
387 // flush counter, unless this is the first value (count = 0)
388 // case 1: just a single value. set first bit to positive
389 // case 2: write several values. set first bit to negative to indicate that there is a length coming
390 self.buf.write_var(encode_diff as i64);
391 if self.count > 1 {
392 self.buf.write_var(self.count - 2);
393 }
394 }
395 }
396
397 fn to_vec(mut self) -> Vec<u8> {
398 self.flush();
399 self.buf
400 }
401}
402
403/// Optimized Rle encoder that does not suffer from the mentioned problem of the basic Rle encoder.
404///
405/// Internally uses VarInt encoder to write unsigned integers. If the input occurs multiple times, we write
406/// write it as a negative number. The UintOptRleDecoder then understands that it needs to read a count.
407///
408/// Encodes [1,2,3,3,3] as [1,2,-3,3] (once 1, once 2, three times 3)
409struct UIntOptRleEncoder {
410 buf: Vec<u8>,
411 last: u64,
412 count: u32,
413}
414
415impl UIntOptRleEncoder {
416 fn new() -> Self {
417 UIntOptRleEncoder {
418 buf: Vec::new(),
419 last: 0,
420 count: 0,
421 }
422 }
423
424 fn write_u64(&mut self, value: u64) {
425 if self.last == value {
426 self.count += 1;
427 } else {
428 self.flush();
429 self.count = 1;
430 self.last = value;
431 }
432 }
433
434 fn to_vec(mut self) -> Vec<u8> {
435 self.flush();
436 self.buf
437 }
438
439 fn flush(&mut self) {
440 if self.count > 0 {
441 // flush counter, unless this is the first value (count = 0)
442 // case 1: just a single value. set sign to positive
443 // case 2: write several values. set sign to negative to indicate that there is a length coming
444 if self.count == 1 {
445 self.buf.write_var(self.last as i64);
446 } else {
447 let value = Signed::new(-(self.last as i64), true);
448 self.buf.write_var_signed(&value);
449 self.buf.write_var(self.count - 2);
450 }
451 }
452 }
453}
454
455/// Basic Run Length Encoder - a basic compression implementation.
456///
457/// Encodes [1,1,1,7] to [1,3,7,1] (3 times 1, 1 time 7). This encoder might do more harm than good if there are a lot of values that are not repeated.
458///
459/// It was originally used for image compression. Cool .. article http://csbruce.com/cbm/transactor/pdfs/trans_v7_i06.pdf
460struct RleEncoder {
461 buf: Vec<u8>,
462 last: Option<u8>,
463 count: u32,
464}
465
466impl RleEncoder {
467 fn new() -> Self {
468 RleEncoder {
469 buf: Vec::new(),
470 last: None,
471 count: 0,
472 }
473 }
474
475 fn write_u8(&mut self, value: u8) {
476 if self.last == Some(value) {
477 self.count += 1;
478 } else {
479 if self.count > 0 {
480 // flush counter, unless this is the first value (count = 0)
481 self.buf.write_var(self.count - 1);
482 }
483 self.count = 1;
484 self.buf.write_u8(value);
485 self.last = Some(value);
486 }
487 }
488
489 fn to_vec(self) -> Vec<u8> {
490 self.buf
491 }
492}
493
494/// Optimized String Encoder.
495///
496/// Encoding many small strings in a simple Encoder is not very efficient. The function call to decode a string takes some time and creates references that must be eventually deleted.
497/// In practice, when decoding several million small strings, the GC will kick in more and more often to collect orphaned string objects (or maybe there is another reason?).
498///
499/// This string encoder solves the above problem. All strings are concatenated and written as a single string using a single encoding call.
500///
501/// The lengths are encoded using a UintOptRleEncoder.
502struct StringEncoder {
503 buf: String,
504 len_encoder: UIntOptRleEncoder,
505}
506
507impl StringEncoder {
508 fn new() -> Self {
509 StringEncoder {
510 buf: String::new(),
511 len_encoder: UIntOptRleEncoder::new(),
512 }
513 }
514
515 fn write(&mut self, str: &str) {
516 let utf16_len = str.encode_utf16().count(); // Yjs encodes offsets using utf-16
517 self.buf.push_str(str);
518 self.len_encoder.write_u64(utf16_len as u64);
519 }
520
521 fn to_vec(self) -> Vec<u8> {
522 let lengths = self.len_encoder.to_vec();
523 let mut buf = Vec::with_capacity(self.buf.len() + lengths.len());
524 buf.write_string(&self.buf);
525 buf.write_all(lengths.as_slice());
526 buf
527 }
528}
529