oficina / docs Public

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

Plain git — no account needed to clone.

Download

Download this file

1//! `alt` module contains a set of auxiliary functions that can be used for common operations
2//! over document [Update]s directly on their binary representation.
3
4use crate::encoding::read::{Cursor, Error};
5use crate::update::Update;
6use crate::updates::decoder::{Decode, DecoderV2};
7use crate::updates::encoder::{Encode, Encoder, EncoderV1, EncoderV2};
8use crate::StateVector;
9
10/// Merges a sequence of updates (encoded using lib0 v1 encoding) together, producing another
11/// update (also lib0 v1 encoded) in the result. Returned binary is a combination of all input
12/// `updates`, compressed.
13///
14/// Returns an error whenever any of the input updates couldn't be decoded.
15pub fn merge_updates_v1<I, B>(updates: I) -> Result<Vec<u8>, Error>
16where
17 I: IntoIterator<Item = B>,
18 B: AsRef<[u8]>,
19{
20 let mut i = updates.into_iter();
21 let (lo, hi) = i.size_hint();
22 let mut merge = Vec::with_capacity(hi.unwrap_or(lo));
23 while let Some(buf) = i.next() {
24 let parsed = Update::decode_v1(buf.as_ref())?;
25 merge.push(parsed);
26 }
27 Ok(Update::merge_updates(merge).encode_v1())
28}
29
30/// Merges a sequence of updates (encoded using lib0 v2 encoding) together, producing another
31/// update (also lib0 v2 encoded) in the result. Returned binary is a combination of all input
32/// `updates`, compressed.
33///
34/// Returns an error whenever any of the input updates couldn't be decoded.
35pub fn merge_updates_v2<I, B>(updates: I) -> Result<Vec<u8>, Error>
36where
37 I: IntoIterator<Item = B>,
38 B: AsRef<[u8]>,
39{
40 let mut i = updates.into_iter();
41 let (lo, hi) = i.size_hint();
42 let mut merge = Vec::with_capacity(hi.unwrap_or(lo));
43 while let Some(buf) = i.next() {
44 let update = Update::decode_v2(buf.as_ref())?;
45 merge.push(update);
46 }
47 Ok(Update::merge_updates(merge).encode_v2())
48}
49
50/// Decodes a input `update` (encoded using lib0 v1 encoding) and returns an encoded [StateVector]
51/// of that update.
52///
53/// Returns an error whenever any of the input update couldn't be decoded.
54pub fn encode_state_vector_from_update_v1(update: &[u8]) -> Result<Vec<u8>, Error> {
55 let update = Update::decode_v1(update)?;
56 Ok(update.state_vector().encode_v1())
57}
58
59/// Decodes a input `update` (encoded using lib0 v2 encoding) and returns an encoded [StateVector]
60/// of that update.
61///
62/// Returns an error whenever any of the input update couldn't be decoded.
63pub fn encode_state_vector_from_update_v2(update: &[u8]) -> Result<Vec<u8>, Error> {
64 let update = Update::decode_v2(update)?;
65 Ok(update.state_vector().encode_v2())
66}
67
68/// Givens an input `update` (encoded using lib0 v1 encoding) of document **A** and an encoded
69/// `state_vector` of document **B**, returns a lib0 v1 encoded update, that contains all changes
70/// from **A** which have not been observed by **B** (based on its state vector).
71///
72/// Returns an error whenever any of the input arguments couldn't be decoded.
73pub fn diff_updates_v1(update: &[u8], state_vector: &[u8]) -> Result<Vec<u8>, Error> {
74 let sv = StateVector::decode_v1(state_vector)?;
75 let update = Update::decode_v1(update)?;
76 let mut encoder = EncoderV1::new();
77 update.encode_diff(&sv, &mut encoder);
78 // for delete set, don't decode/encode it - just copy the remaining part from the decoder
79 let result = encoder.to_vec();
80 Ok(result)
81}
82
83/// Givens an input `update` (encoded using lib0 v2 encoding) of document **A** and an encoded
84/// `state_vector` of document **B**, returns a lib0 v2 encoded update, that contains all changes
85/// from **A** which have not been observed by **B** (based on its state vector).
86///
87/// Returns an error whenever any of the input arguments couldn't be decoded.
88pub fn diff_updates_v2(update: &[u8], state_vector: &[u8]) -> Result<Vec<u8>, Error> {
89 let sv = StateVector::decode_v2(state_vector)?;
90 let cursor = Cursor::new(update);
91 let mut decoder = DecoderV2::new(cursor)?;
92 let update = Update::decode(&mut decoder)?;
93 let mut encoder = EncoderV2::new();
94 update.encode_diff(&sv, &mut encoder);
95 // for delete set, don't decode/encode it - just copy the remaining part from the decoder
96 Ok(encoder.to_vec())
97}
98
99#[cfg(test)]
100mod test {
101 use crate::{diff_updates_v1, encode_state_vector_from_update_v1, merge_updates_v1};
102
103 #[test]
104 fn merge_updates_compatibility_v1() {
105 let a = vec![
106 1, 1, 220, 240, 237, 172, 15, 0, 4, 1, 4, 116, 101, 115, 116, 3, 97, 98, 99, 0,
107 ];
108 let b = vec![
109 1, 1, 201, 139, 250, 201, 1, 0, 4, 1, 4, 116, 101, 115, 116, 2, 100, 101, 0,
110 ];
111 let expected = vec![
112 2, 1, 220, 240, 237, 172, 15, 0, 4, 1, 4, 116, 101, 115, 116, 3, 97, 98, 99, 1, 201,
113 139, 250, 201, 1, 0, 4, 1, 4, 116, 101, 115, 116, 2, 100, 101, 0,
114 ];
115
116 let actual = merge_updates_v1(&[a, b]).unwrap();
117 assert_eq!(actual, expected);
118 }
119
120 #[test]
121 fn merge_updates_compatibility_v1_2() {
122 let a = &[
123 1, 1, 129, 231, 135, 164, 7, 0, 4, 1, 4, 49, 50, 51, 52, 1, 97, 0,
124 ];
125 let b = &[
126 1, 1, 129, 231, 135, 164, 7, 1, 68, 129, 231, 135, 164, 7, 0, 1, 98, 0,
127 ];
128 let expected = &[
129 1, 2, 129, 231, 135, 164, 7, 0, 4, 1, 4, 49, 50, 51, 52, 1, 97, 68, 129, 231, 135, 164,
130 7, 0, 1, 98, 0,
131 ];
132
133 let actual = merge_updates_v1(&[a, b]).unwrap();
134 assert_eq!(actual, expected);
135 }
136
137 #[test]
138 fn encode_state_vector_compatibility_v1() {
139 let update = &[
140 2, 1, 220, 240, 237, 172, 15, 0, 4, 1, 4, 116, 101, 115, 116, 3, 97, 98, 99, 1, 201,
141 139, 250, 201, 1, 0, 4, 1, 4, 116, 101, 115, 116, 2, 100, 101, 0,
142 ];
143 let expected = &[2, 220, 240, 237, 172, 15, 3, 201, 139, 250, 201, 1, 2];
144 let actual = encode_state_vector_from_update_v1(update).unwrap();
145 assert_eq!(actual, expected);
146 }
147
148 #[test]
149 fn diff_updates_compatibility_v1() {
150 let state_vector = &[1, 148, 189, 145, 162, 9, 3];
151 let update = &[
152 1, 2, 148, 189, 145, 162, 9, 0, 4, 1, 4, 116, 101, 115, 116, 3, 97, 98, 99, 68, 148,
153 189, 145, 162, 9, 0, 2, 100, 101, 0,
154 ];
155 let expected = &[
156 1, 1, 148, 189, 145, 162, 9, 3, 68, 148, 189, 145, 162, 9, 0, 2, 100, 101, 0,
157 ];
158 let actual = diff_updates_v1(update, state_vector).unwrap();
159 assert_eq!(actual, expected);
160 }
161}
162