use std::collections::BTreeSet;
use crate::decode::decode_layered;
pub struct EncodeParams {
pub k: usize,
pub m: usize,
pub n: usize,
pub q: usize,
pub t: usize,
pub nu: usize,
pub sub_chunk_no: usize,
pub original_count: usize,
pub recovery_count: usize,
}
pub fn encode(params: &EncodeParams, data: &[u8]) -> Vec<Vec<u8>> {
let min_sub_chunk_size = 2;
let min_size = params.k * params.sub_chunk_no * min_sub_chunk_size;
let padded_len = if data.is_empty() {
min_size
} else {
let aligned = ((data.len() + min_size - 1) / min_size) * min_size;
aligned.max(min_size)
};
let chunk_size = padded_len / params.k;
let sub_chunk_size = chunk_size / params.sub_chunk_no;
let mut padded_data = data.to_vec();
padded_data.resize(padded_len, 0);
let total_nodes = params.q * params.t; let mut chunks: Vec<Vec<u8>> = vec![vec![0u8; chunk_size]; total_nodes];
for i in 0..params.k {
chunks[i].copy_from_slice(&padded_data[i * chunk_size..(i + 1) * chunk_size]);
}
let parity_start = params.k + params.nu;
let mut nodes_to_compute: BTreeSet<usize> = BTreeSet::new();
for i in parity_start..total_nodes {
nodes_to_compute.insert(i);
}
decode_layered(params, &nodes_to_compute, &mut chunks, sub_chunk_size)
.expect("Encode failed: this indicates a bug in ClayCode");
let mut result = Vec::with_capacity(params.n);
for i in 0..params.k {
result.push(chunks[i].clone());
}
for i in (params.k + params.nu)..total_nodes {
result.push(chunks[i].clone());
}
result
}
#[cfg(test)]
mod tests {
use super::*;
fn test_params() -> EncodeParams {
EncodeParams {
k: 4,
m: 2,
n: 6,
q: 2,
t: 3,
nu: 0,
sub_chunk_no: 8,
original_count: 4,
recovery_count: 2,
}
}
#[test]
fn test_encode_produces_correct_chunk_count() {
let params = test_params();
let data = b"Test data for encoding";
let chunks = encode(¶ms, data);
assert_eq!(chunks.len(), params.n);
}
#[test]
fn test_encode_empty_data() {
let params = test_params();
let chunks = encode(¶ms, &[]);
assert_eq!(chunks.len(), params.n);
let chunk_size = chunks[0].len();
for chunk in &chunks {
assert_eq!(chunk.len(), chunk_size);
}
}
#[test]
fn test_encode_chunk_alignment() {
let params = test_params();
let data = vec![0xABu8; 100];
let chunks = encode(¶ms, &data);
for chunk in &chunks {
assert_eq!(chunk.len() % params.sub_chunk_no, 0);
}
}
}