1use ps_buffer::Buffer;
2
3use crate::{codeword::Codeword, long, DecodeError, EncodeError, ReedSolomon};
4
5pub fn encode(message: &[u8], parity: u8) -> Result<Buffer, EncodeError> {
10 if message.len() + (usize::from(parity) << 1) > 0xff {
11 let segment_length = 0xFF - (parity << 1);
12 let codeword = long::encode(message, parity, segment_length, segment_length)?;
13
14 return Ok(codeword);
15 }
16
17 let rs = ReedSolomon::new(parity)?;
18
19 Ok(rs.encode(message)?)
20}
21
22pub fn decode(received: &[u8], parity: u8) -> Result<Codeword, DecodeError> {
28 if let Ok(length) = u8::try_from(received.len()) {
29 if parity > length >> 1 {
30 return Err(DecodeError::InsufficientParityBytes(parity, length));
31 }
32
33 let rs = ReedSolomon::new(parity)?;
34
35 Ok(rs.decode(received)?)
36 } else {
37 Ok(long::decode(received)?)
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use crate::EccError;
44
45 use super::{decode, encode};
46
47 #[test]
48 fn ecc_works() -> Result<(), EccError> {
49 let test_str = "Strč prst skrz krk! ¯\\_(ツ)_/¯".as_bytes();
50 let mut encoded = encode(test_str, 13)?;
51
52 for i in 0..13 {
53 let index = (i * 37) % encoded.len();
54 encoded[index] ^= (i * index + 13).to_le_bytes()[0];
55 let decoded = decode(&encoded, 13)?;
56
57 assert_eq!(test_str, &decoded[..]);
58 }
59
60 Ok(())
61 }
62}