1use std::collections::BTreeSet;
6
7use crate::decode::decode_layered;
8
9pub struct EncodeParams {
11 pub k: usize,
12 pub m: usize,
13 pub n: usize,
14 pub q: usize,
15 pub t: usize,
16 pub nu: usize,
17 pub sub_chunk_no: usize,
18 pub original_count: usize,
19 pub recovery_count: usize,
20}
21
22pub fn encode(params: &EncodeParams, data: &[u8]) -> Vec<Vec<u8>> {
31 let min_sub_chunk_size = 2;
34 let min_size = params.k * params.sub_chunk_no * min_sub_chunk_size;
35 let padded_len = if data.is_empty() {
36 min_size
37 } else {
38 let aligned = ((data.len() + min_size - 1) / min_size) * min_size;
39 aligned.max(min_size)
40 };
41 let chunk_size = padded_len / params.k;
42 let sub_chunk_size = chunk_size / params.sub_chunk_no;
43
44 let mut padded_data = data.to_vec();
46 padded_data.resize(padded_len, 0);
47
48 let total_nodes = params.q * params.t; let mut chunks: Vec<Vec<u8>> = vec![vec![0u8; chunk_size]; total_nodes];
51
52 for i in 0..params.k {
54 chunks[i].copy_from_slice(&padded_data[i * chunk_size..(i + 1) * chunk_size]);
55 }
56
57 let parity_start = params.k + params.nu;
60 let mut nodes_to_compute: BTreeSet<usize> = BTreeSet::new();
61 for i in parity_start..total_nodes {
62 nodes_to_compute.insert(i);
63 }
64
65 decode_layered(params, &nodes_to_compute, &mut chunks, sub_chunk_size)
68 .expect("Encode failed: this indicates a bug in ClayCode");
69
70 let mut result = Vec::with_capacity(params.n);
72 for i in 0..params.k {
73 result.push(chunks[i].clone());
74 }
75 for i in (params.k + params.nu)..total_nodes {
76 result.push(chunks[i].clone());
77 }
78
79 result
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 fn test_params() -> EncodeParams {
87 EncodeParams {
89 k: 4,
90 m: 2,
91 n: 6,
92 q: 2,
93 t: 3,
94 nu: 0,
95 sub_chunk_no: 8,
96 original_count: 4,
97 recovery_count: 2,
98 }
99 }
100
101 #[test]
102 fn test_encode_produces_correct_chunk_count() {
103 let params = test_params();
104 let data = b"Test data for encoding";
105 let chunks = encode(¶ms, data);
106 assert_eq!(chunks.len(), params.n);
107 }
108
109 #[test]
110 fn test_encode_empty_data() {
111 let params = test_params();
112 let chunks = encode(¶ms, &[]);
113 assert_eq!(chunks.len(), params.n);
114 let chunk_size = chunks[0].len();
116 for chunk in &chunks {
117 assert_eq!(chunk.len(), chunk_size);
118 }
119 }
120
121 #[test]
122 fn test_encode_chunk_alignment() {
123 let params = test_params();
124 let data = vec![0xABu8; 100];
125 let chunks = encode(¶ms, &data);
126
127 for chunk in &chunks {
129 assert_eq!(chunk.len() % params.sub_chunk_no, 0);
130 }
131 }
132}