use arrayvec::ArrayVec; use labrador_ldpc::LDPCCode; use crate::error::EncodeError; macro_rules! enc_chunk { ($d:ident, $i:ident, $t:ident, $n:literal) => { ::paste::paste! { let mut codeword = [0; $n * 2]; codeword[0..$n].copy_from_slice(&$d[$i..($i + $n)]); labrador_ldpc::LDPCCode::[<$t>].encode(&mut codeword); $d.try_extend_from_slice(&codeword[$n..]) .map_err(|_| EncodeError::CatsOverflow)?; $i += $n; } }; } // On failure this still modifies the data array! pub(crate) fn encode<const N: usize>(data: &mut ArrayVec<u8, N>) -> Result<(), EncodeError> { let mut i = 0; let n = data.len(); loop { match n - i { 512.. => { enc_chunk!(data, i, TM8192, 512); } 128.. => { enc_chunk!(data, i, TM2048, 128); } 32.. => { enc_chunk!(data, i, TC512, 32); } 16.. => { enc_chunk!(data, i, TC256, 16); } 8.. => { enc_chunk!(data, i, TC128, 8); } 0 => break, _ => { let mut codeword = [0xAA; 16]; codeword[0..(n - i)].copy_from_slice(&data[i..n]); LDPCCode::TC128.encode(&mut codeword); data.try_extend_from_slice(&codeword[8..]) .map_err(|_| EncodeError::CatsOverflow)?; i = n; } } } data.try_extend_from_slice(&u16::try_from(n).unwrap().to_le_bytes()) .map_err(|_| EncodeError::CatsOverflow)?; Ok(()) } pub(crate) fn decode<const N: usize>(data: &mut ArrayVec<u8, N>) -> Option<()> { if data.len() < 2 { return None; } let len = [data[data.len() - 2], data[data.len() - 1]]; let len = u16::from_le_bytes(len).into(); let (data, parity) = data.split_at_mut(len); let parity = parity.get(0..parity.len().checked_sub(2)?)?; let mut di = 0; let mut pi = 0; let working = todo!(); loop { match data.len() - di { 512.. => {} 128.. => {} 32.. => {} 16.. => {} 8.. => {} 0.. => {} _ => {} } } Some(()) } #[cfg(test)] mod tests { use super::*; use arrayvec::ArrayVec; #[test] fn len_test() { // from the example in the docs let mut data: ArrayVec<u8, 8191> = ArrayVec::new(); for _ in 0..41 { data.extend( b"Example packet data wueirpqwerwrywqoeiruy29346129384761" .iter() .cloned(), ); } data.extend( b"Example packet data wueirpqwerwrywqoeiru346129384761" .iter() .cloned(), ); assert_eq!(2349, data.len()); encode(&mut data).unwrap(); assert_eq!(4703, data.len()); } #[test] fn basic_encode_decode() { let mut data: ArrayVec<u8, 8191> = ArrayVec::new(); for _ in 0..50 { data.extend( b"This is a test packet. jsalksjd093809324JASLD:LKD*#$)(*#@)" .iter() .cloned(), ); } let orig = data.clone(); encode(&mut data).unwrap(); assert_ne!(orig, data); decode(&mut data).unwrap(); assert_eq!(orig, data); } #[test] fn encode_decode_with_bit_flips() { let mut data: ArrayVec<u8, 8191> = ArrayVec::new(); for _ in 0..50 { data.extend( b"jsalksjd093809324JASLD:LKD*#$)(*#@) Another test packet" .iter() .cloned(), ); } let orig = data.clone(); encode(&mut data).unwrap(); assert_ne!(orig, data); data[234] ^= 0x55; data[0] ^= 0xAA; data[999] ^= 0x43; decode(&mut data).unwrap(); assert_eq!(orig, data); } }