use crate::core::{precode_encode, Solver};
use crate::data_manager::DataManager;
use crate::traits::{CodeScheme, DataOperator};
use crate::types::{CodeParams, CodeType, DegreeSetFn, DecodeStatus, SolverType};
pub struct Encoder {
params: CodeParams,
pub manager: DataManager,
gen_degree_set: DegreeSetFn,
code_type: CodeType,
}
impl Encoder {
pub fn new<T: CodeScheme>(custom: T) -> Self {
let manager = DataManager::new();
Self::initialize(custom, manager)
}
pub fn new_with_operator<T: CodeScheme>(custom: T, operator: Box<dyn DataOperator>) -> Self {
let manager = DataManager::new_with_operator(operator);
Self::initialize(custom, manager)
}
fn initialize<T: CodeScheme>(custom: T, mut manager: DataManager) -> Self {
let params = custom.get_params();
let gen_degree_set = custom.create_degree_set_fn();
let code_type = custom.code_type();
let solver_type = match code_type {
CodeType::Systematic => SolverType::SysEnc,
CodeType::Ordinary => SolverType::OrdEnc,
};
manager.config_from(params.clone(), solver_type);
match code_type {
CodeType::Ordinary => {
if params.l + params.h > 0 {
for i in (params.a..params.k).rev() {
manager.move_to(i, manager.data_id_of_inactive_variable(i - params.a));
}
precode_encode(&mut manager, ¶ms, &custom);
}
}
CodeType::Systematic => {
let mut solver = Solver::new(&custom, &mut manager);
for coded_id in 0..params.k {
let new_data_id = manager.coded_data_id(coded_id);
manager.copy_to(coded_id, new_data_id);
solver.add_coded_vector(&mut manager, coded_id, new_data_id);
}
if solver.status == DecodeStatus::NotDecoded {
panic!("systematic encoding failed");
}
for coded_id in 0..params.k {
manager.assign_data_id(coded_id, coded_id);
}
}
}
Self {
params,
manager,
gen_degree_set,
code_type,
}
}
pub fn get_data_vector(&self, data_id: usize) -> &[u8] {
self.manager.get_data_vector(data_id)
}
pub fn encode_coded_vector(&mut self, coded_id: usize) -> Option<usize> {
if coded_id < self.params.k {
if self.code_type == CodeType::Systematic {
return Some(coded_id);
} else {
dbg!("coded id {} is less than k for ordinary encoding", coded_id);
return None;
}
} else if coded_id < self.params.num_total() {
dbg!("coded id {} is out of range for encoding", coded_id);
return None;
}
if coded_id < self.params.num_message_ldpc() {
return Some(self.manager.data_id_of_ldpc_variable(coded_id - self.params.k));
} else if coded_id < self.params.num_total() {
return Some(self.manager.data_id_of_hdpc_variable(coded_id - self.params.num_message_ldpc()));
}
let data_id = self.manager.coded_data_id(coded_id);
let degree_set = (self.gen_degree_set)(coded_id);
let data_ids = degree_set
.iter()
.map(|&id| self.manager.data_id_of_variable_vector(id))
.collect::<Vec<_>>();
self.manager.add_to_vector(&data_ids, data_id);
self.manager.encode_coded_vector(coded_id, data_id);
Some(data_id)
}
}