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

Function encode

nodedb-codec/src/rans.rs:45–124  ·  view source on GitHub ↗

Compress bytes using interleaved rANS.

(data: &[u8])

Source from the content-addressed store, hash-verified

43
44/// Compress bytes using interleaved rANS.
45pub fn encode(data: &[u8]) -> Vec<u8> {
46 if data.is_empty() {
47 let out = vec![0u8; HEADER_SIZE];
48 // uncompressed_size = 0, freq table = all zeros, compressed_size = 0
49 return out;
50 }
51
52 // Build frequency table.
53 let mut freqs = [0u32; 256];
54 for &b in data {
55 freqs[b as usize] += 1;
56 }
57
58 // Normalize frequencies to sum to PROB_SCALE.
59 let norm_freqs = normalize_frequencies(&freqs, data.len());
60
61 // Build cumulative frequency table.
62 let (cum_freqs, sym_freqs) = build_cum_table(&norm_freqs);
63
64 // Encode using 4 interleaved streams.
65 // Each stream processes every 4th byte: stream 0 gets bytes 0,4,8,...
66 let mut streams: [Vec<u8>; NUM_STREAMS] = std::array::from_fn(|_| Vec::new());
67 let mut states = [RANS_L; NUM_STREAMS];
68
69 // Encode in REVERSE order (rANS encodes backward, decodes forward).
70 for i in (0..data.len()).rev() {
71 let stream_idx = i % NUM_STREAMS;
72 let sym = data[i] as usize;
73 let freq = sym_freqs[sym];
74 let start = cum_freqs[sym];
75
76 if freq == 0 {
77 continue; // Symbol with zero frequency — shouldn't happen after normalization.
78 }
79
80 rans_encode_symbol(
81 &mut states[stream_idx],
82 &mut streams[stream_idx],
83 start,
84 freq,
85 );
86 }
87
88 // Flush final states.
89 for i in 0..NUM_STREAMS {
90 let s = states[i];
91 streams[i].push((s & 0xFF) as u8);
92 streams[i].push(((s >> 8) & 0xFF) as u8);
93 streams[i].push(((s >> 16) & 0xFF) as u8);
94 streams[i].push(((s >> 24) & 0xFF) as u8);
95 }
96
97 // Build output.
98 let total_compressed: usize = streams.iter().map(|s| s.len()).sum();
99 let mut out = Vec::with_capacity(HEADER_SIZE + total_compressed + NUM_STREAMS * 4);
100
101 // Header: uncompressed size.
102 out.extend_from_slice(&(data.len() as u32).to_le_bytes());

Callers 8

empty_roundtripFunction · 0.70
single_byteFunction · 0.70
repeated_bytesFunction · 0.70
text_dataFunction · 0.70
uniform_random_dataFunction · 0.70
all_byte_valuesFunction · 0.70
skewed_distributionFunction · 0.70

Calls 8

normalize_frequenciesFunction · 0.85
build_cum_tableFunction · 0.85
rans_encode_symbolFunction · 0.85
sumMethod · 0.80
is_emptyMethod · 0.45
lenMethod · 0.45
pushMethod · 0.45
iterMethod · 0.45

Tested by 8

empty_roundtripFunction · 0.56
single_byteFunction · 0.56
repeated_bytesFunction · 0.56
text_dataFunction · 0.56
uniform_random_dataFunction · 0.56
all_byte_valuesFunction · 0.56
skewed_distributionFunction · 0.56