use anyhow::Result;
use everscale_raptorq::{Encoder, EncodingPacket};
use crate::proto::rldp::RaptorQFecType;
pub struct RaptorQEncoder {
engine: Encoder,
params: RaptorQFecType,
source_packets: Vec<EncodingPacket>,
encoder_index: usize,
}
impl RaptorQEncoder {
pub fn with_data(data: &[u8]) -> Self {
let engine = Encoder::with_defaults(data, MAX_TRANSMISSION_UNIT as u16);
let source_packets = engine
.get_block_encoders()
.iter()
.flat_map(|encoder| encoder.source_packets().into_iter().rev())
.collect::<Vec<_>>();
Self {
engine,
params: RaptorQFecType {
total_len: data.len() as u32,
packet_len: MAX_TRANSMISSION_UNIT,
packet_count: source_packets.len() as u32,
},
source_packets,
encoder_index: 0,
}
}
pub fn encode(&mut self, seqno: &mut u32) -> Result<Vec<u8>> {
let packet = if let Some(packet) = self.source_packets.pop() {
packet
} else {
let encoders = self.engine.get_block_encoders();
let packet = match encoders[self.encoder_index].repair_packets(*seqno, 1).pop() {
Some(packet) => packet,
None => return Err(EncoderError::FailedToEncode.into()),
};
self.encoder_index = (self.encoder_index + 1) % encoders.len();
packet
};
let (payload_id, data) = packet.split();
*seqno = payload_id.encoding_symbol_id();
Ok(data)
}
#[inline(always)]
pub fn params(&self) -> &RaptorQFecType {
&self.params
}
}
#[derive(thiserror::Error, Debug)]
enum EncoderError {
#[error("Failed to encode repair packet")]
FailedToEncode,
}
pub const MAX_TRANSMISSION_UNIT: u32 = 768;