Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4faa5df

Browse files
authored
feat: encode doc into binary (#441)
1 parent bc63b9a commit 4faa5df

3 files changed

Lines changed: 118 additions & 1 deletion

File tree

libs/jwst-codec/src/doc/codec/update.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ mod tests {
393393
use super::*;
394394
use serde::Deserialize;
395395
use std::{num::ParseIntError, path::PathBuf};
396+
use yrs::{Map, Transact};
396397

397398
fn struct_item(id: (Client, Clock), len: usize) -> StructInfo {
398399
StructInfo::Item {
@@ -581,4 +582,23 @@ mod tests {
581582
&OrderRange::from(vec![(10..12), (13..15)])
582583
);
583584
}
585+
586+
#[test]
587+
fn double_run_test_with_yrs_basic() {
588+
let yrs_doc = yrs::Doc::new();
589+
590+
let map = yrs_doc.get_or_insert_map("abc");
591+
let mut trx = yrs_doc.transact_mut();
592+
map.insert(&mut trx, "a", 1).unwrap();
593+
594+
let binary_from_yrs = trx.encode_update_v1().unwrap();
595+
596+
let mut decoder = RawDecoder::new(binary_from_yrs.clone());
597+
let update = Update::read(&mut decoder).unwrap();
598+
let mut doc = Doc::default();
599+
doc.apply_update(update).unwrap();
600+
let binary = doc.encode_update_v1().unwrap();
601+
602+
assert_eq!(binary_from_yrs, binary);
603+
}
584604
}

libs/jwst-codec/src/doc/document.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,4 +416,12 @@ impl Doc {
416416
Ok(())
417417
})
418418
}
419+
420+
pub fn encode_update_v1(self) -> JwstCodecResult<Vec<u8>> {
421+
let store = self.store;
422+
let mut encoder = RawEncoder::default();
423+
store.encode_with_state_vector(&StateVector::default(), &mut encoder)?;
424+
425+
Ok(encoder.into_inner())
426+
}
419427
}

libs/jwst-codec/src/doc/store.rs

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::*;
22
use crate::doc::StateVector;
3+
use std::collections::VecDeque;
34
use std::{
45
cell::{Ref, RefCell, RefMut},
56
collections::{hash_map::Entry, HashMap},
@@ -10,6 +11,21 @@ use std::{
1011
#[derive(Clone, PartialEq, Debug)]
1112
pub struct StructRef(Arc<RefCell<StructInfo>>);
1213

14+
impl StructRef {
15+
pub fn read<R: CrdtReader>(decoder: &mut R, id: Id) -> JwstCodecResult<Self> {
16+
match StructInfo::read(decoder, id) {
17+
Ok(info) => Ok(info.into()),
18+
Err(err) => Err(err),
19+
}
20+
}
21+
}
22+
23+
impl<W: CrdtWriter> CrdtWrite<W> for StructRef {
24+
fn write(&self, writer: &mut W) -> JwstCodecResult {
25+
self.0.borrow().write(writer)
26+
}
27+
}
28+
1329
impl From<StructInfo> for StructRef {
1430
fn from(info: StructInfo) -> Self {
1531
Self(Arc::new(RefCell::new(info)))
@@ -91,8 +107,10 @@ impl StructRef {
91107
#[derive(Default)]
92108
pub struct DocStore {
93109
pub items: Arc<RwLock<HashMap<Client, Vec<StructRef>>>>,
94-
pub types: Arc<RwLock<HashMap<String, TypeStoreRef>>>,
95110
pub delete_set: Arc<RwLock<DeleteSet>>,
111+
112+
// following fields are only used in memory
113+
pub types: Arc<RwLock<HashMap<String, TypeStoreRef>>>,
96114
pub pending: Option<Update>,
97115
}
98116

@@ -361,6 +379,77 @@ impl DocStore {
361379
delete_set.add(id.client, id.clock, len)
362380
}
363381
}
382+
383+
fn diff_state_vectors(
384+
local_state_vector: &StateVector,
385+
remote_state_vector: &StateVector,
386+
) -> Vec<(Client, Clock)> {
387+
let mut diff = Vec::new();
388+
389+
for (client, &remote_clock) in remote_state_vector.iter() {
390+
let local_clock = local_state_vector.get(client);
391+
if local_clock > remote_clock {
392+
diff.push((*client, remote_clock));
393+
}
394+
}
395+
396+
for (client, _) in local_state_vector.iter() {
397+
if remote_state_vector.get(client) == 0 {
398+
diff.push((*client, 0));
399+
}
400+
}
401+
402+
diff
403+
}
404+
405+
pub fn encode_with_state_vector<W: CrdtWriter>(
406+
&self,
407+
sv: &StateVector,
408+
encoder: &mut W,
409+
) -> JwstCodecResult {
410+
let local_state_vector = self.get_state_vector();
411+
let diff = Self::diff_state_vectors(&local_state_vector, sv);
412+
let mut update_structs: HashMap<u64, VecDeque<StructInfo>> = HashMap::new();
413+
414+
for (client, clock) in diff {
415+
// We have made sure that the client is in the local state vector in diff_state_vectors()
416+
if let Some(items) = self.items.read().unwrap().get(&client) {
417+
if items.is_empty() {
418+
continue;
419+
}
420+
421+
update_structs.insert(client, VecDeque::new());
422+
let vec_struct_info = update_structs.get_mut(&client).unwrap();
423+
424+
// the smallest clock in items may exceed the clock
425+
let clock = items.first().unwrap().id().clock.max(clock);
426+
if let Some(index) = Self::get_item_index(items, clock) {
427+
let first_block = items.get(index).unwrap();
428+
let offset = first_block.clock() - clock;
429+
if offset != 0 {
430+
// needs to implement Content split first
431+
unimplemented!()
432+
} else {
433+
vec_struct_info.push_back(first_block.borrow().clone());
434+
}
435+
436+
for item in items.iter().skip(index + 1) {
437+
vec_struct_info.push_back(item.borrow().clone());
438+
}
439+
}
440+
}
441+
}
442+
443+
let update = Update {
444+
structs: update_structs,
445+
delete_set: self.delete_set.read().unwrap().clone(),
446+
..Update::default()
447+
};
448+
449+
update.write(encoder)?;
450+
451+
Ok(())
452+
}
364453
}
365454

366455
#[cfg(test)]

0 commit comments

Comments
 (0)