MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / encode

Function encode

nodedb-codec/src/crdt_compress.rs:40–92  ·  view source on GitHub ↗

Compressed CRDT operation batch. Wire format: ```text [4 bytes] op count (LE u32) [2 bytes] actor dictionary size (LE u16) [actor_count × 8 bytes] actor IDs (LE u64) [N bytes] Delta-encoded Lamport timestamps (nodedb-codec delta format) [4 bytes] actor_index block size (LE u32) [M bytes] actor indices (u8 if ≤256 actors, u16 otherwise) [4 bytes] content block size (LE u32) [K bytes] FSST-compress

(ops: &[CrdtOp])

Source from the content-addressed store, hash-verified

38/// [K bytes] FSST-compressed content (newline-delimited)
39/// ```
40pub fn encode(ops: &[CrdtOp]) -> Result<Vec<u8>, CodecError> {
41 if ops.is_empty() {
42 return Ok(0u32.to_le_bytes().to_vec());
43 }
44
45 let count = ops.len() as u32;
46
47 // Build actor dictionary.
48 let mut actor_dict: Vec<u64> = Vec::new();
49 let mut actor_map = std::collections::HashMap::new();
50 for op in ops {
51 actor_map.entry(op.actor_id).or_insert_with(|| {
52 let idx = actor_dict.len() as u16;
53 actor_dict.push(op.actor_id);
54 idx
55 });
56 }
57
58 // Delta-encode Lamport timestamps.
59 let lamports: Vec<i64> = ops.iter().map(|op| op.lamport as i64).collect();
60 let lamport_block = crate::delta::encode(&lamports);
61
62 // Actor indices.
63 let use_u8 = actor_dict.len() <= 256;
64 let actor_indices: Vec<u8> = if use_u8 {
65 ops.iter().map(|op| actor_map[&op.actor_id] as u8).collect()
66 } else {
67 ops.iter()
68 .flat_map(|op| actor_map[&op.actor_id].to_le_bytes())
69 .collect()
70 };
71
72 // FSST-compress content (treat each op's content as a separate string).
73 let content_refs: Vec<&[u8]> = ops.iter().map(|op| op.content.as_slice()).collect();
74 let content_block = crate::fsst::encode(&content_refs);
75
76 // Build output.
77 let mut out = Vec::new();
78 out.extend_from_slice(&count.to_le_bytes());
79 out.extend_from_slice(&(actor_dict.len() as u16).to_le_bytes());
80 for &actor in &actor_dict {
81 out.extend_from_slice(&actor.to_le_bytes());
82 }
83 out.extend_from_slice(&(lamport_block.len() as u32).to_le_bytes());
84 out.extend_from_slice(&lamport_block);
85 out.push(if use_u8 { 1 } else { 2 }); // index width marker
86 out.extend_from_slice(&(actor_indices.len() as u32).to_le_bytes());
87 out.extend_from_slice(&actor_indices);
88 out.extend_from_slice(&(content_block.len() as u32).to_le_bytes());
89 out.extend_from_slice(&content_block);
90
91 Ok(out)
92}
93
94/// Decode compressed CRDT operations.
95pub fn decode(data: &[u8]) -> Result<Vec<CrdtOp>, CodecError> {

Callers 4

empty_roundtripFunction · 0.70
basic_roundtripFunction · 0.70
actor_dictionary_dedupFunction · 0.70

Calls 8

entryMethod · 0.80
collectMethod · 0.80
is_emptyMethod · 0.45
to_vecMethod · 0.45
lenMethod · 0.45
pushMethod · 0.45
iterMethod · 0.45
as_sliceMethod · 0.45

Tested by 4

empty_roundtripFunction · 0.56
basic_roundtripFunction · 0.56
actor_dictionary_dedupFunction · 0.56