1use alloc::vec::Vec;
2
3use crate::partition::Partition;
4use crate::{common, raptor};
5
6pub struct SourceBlockEncoder {
8 intermediate: Vec<Vec<u8>>,
9 k: u32,
10 l: u32,
11 l_prime: u32,
12}
13
14impl SourceBlockEncoder {
15 pub fn new(source_block: &[u8], max_source_symbols: usize) -> Self {
27 let partition = Partition::new(source_block.len(), max_source_symbols);
28 let source_block = partition.create_source_block(source_block);
29 let k = source_block.len() as u32;
30 let mut raptor = raptor::Raptor::new(k);
31 raptor.add_encoding_symbols(&source_block);
32 raptor.reduce();
33
34 SourceBlockEncoder {
35 intermediate: raptor.intermediate_symbols().to_vec(),
36 k,
37 l: raptor.get_l(),
38 l_prime: raptor.get_l_prime(),
39 }
40 }
41
42 pub fn nb_source_symbols(&self) -> u32 {
44 self.k
45 }
46
47 pub fn fountain(&mut self, esi: u32) -> Vec<u8> {
63 let mut block = Vec::new();
64 let indices = common::find_lt_indices(self.k, esi, self.l, self.l_prime);
65 for indice in indices {
66 if indice < self.intermediate.len() as u32 {
67 common::xor(&mut block, &self.intermediate[indice as usize]);
68 }
69 }
70
71 block
72 }
73}
74
75pub fn encode_source_block(
94 source_block: &[u8],
95 max_source_symbols: usize,
96 nb_repair: usize,
97) -> (Vec<Vec<u8>>, u32) {
98 let mut encoder = SourceBlockEncoder::new(source_block, max_source_symbols);
99 let mut output: Vec<Vec<u8>> = Vec::new();
100 let n = encoder.nb_source_symbols() as usize + nb_repair;
101 for esi in 0..n as u32 {
102 output.push(encoder.fountain(esi));
103 }
104 (output, encoder.nb_source_symbols())
105}
106
107#[cfg(test)]
108mod tests {
109 use alloc::vec;
110 use alloc::vec::Vec;
111
112 #[test]
113 fn test_source_block_encoder() {
114 crate::tests::init();
115
116 let input: Vec<u8> = vec![1, 2, 7, 4, 0, 2, 54, 4, 1, 1, 10, 200, 1, 21, 3, 80];
117 let max_source_symbols = 4;
118 let nb_repair = 3;
119
120 let (encoded_block, k) = super::encode_source_block(&input, max_source_symbols, nb_repair);
121 log::debug!("Encoded with {} blocks", k);
122
123 let mut encoded_block: Vec<Option<Vec<u8>>> = encoded_block
126 .into_iter()
127 .map(|symbols| Some(symbols))
128 .collect();
129
130 encoded_block[0] = None;
132 encoded_block[1] = None;
133
134 let output =
135 crate::decoder::decode_source_block(&encoded_block, k as usize, input.len()).unwrap();
136 log::debug!("{:?} / {:?}", output, input);
137 assert!(output.len() == input.len());
138 assert!(output == input);
139 }
140}