ps_ecc/reed_solomon/methods/
correct.rs1use ps_buffer::Buffer;
2
3use crate::cow::Cow;
4use crate::{RSDecodeError, ReedSolomon};
5
6impl ReedSolomon {
7 pub fn correct<'lt>(&self, received: &'lt [u8]) -> Result<Cow<'lt>, RSDecodeError> {
19 let parity_bytes = self.parity_bytes();
20
21 if received.len() < usize::from(parity_bytes) {
22 return Err(RSDecodeError::InsufficientLength {
23 parity_bytes,
24 received: received.len(),
25 });
26 }
27
28 let received_len = u8::try_from(received.len())?;
29 let syndromes = Self::compute_syndromes(parity_bytes, received);
30
31 let Some(errors) = self.compute_errors(received_len, &syndromes)? else {
32 return Ok(Cow::Borrowed(received));
33 };
34
35 let mut corrected = Buffer::from_slice(received)?;
37
38 Self::apply_corrections(
39 &mut corrected,
40 errors.first_n_coefficients(received_len.into()),
41 );
42
43 match self.validate(&corrected) {
44 None => Ok(corrected.into()),
45 Some(_) => Err(RSDecodeError::TooManyErrors),
46 }
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use crate::{RSDecodeError, ReedSolomon};
53
54 type TestError = Box<dyn std::error::Error>;
55
56 #[test]
57 fn test_correct_rejects_input_shorter_than_parity() -> Result<(), TestError> {
58 let rs = ReedSolomon::new(4)?;
61
62 for received in [&[][..], &[0u8; 7][..]] {
63 assert_eq!(
64 rs.correct(received),
65 Err(RSDecodeError::InsufficientLength {
66 parity_bytes: 8,
67 received: received.len(),
68 })
69 );
70 }
71
72 Ok(())
73 }
74
75 #[test]
76 fn test_correct_accepts_parity_only_codeword() -> Result<(), TestError> {
77 let rs = ReedSolomon::new(4)?;
78 let encoded = rs.encode(&[])?;
79 let corrected = rs.correct(&encoded)?;
80
81 assert_eq!(&corrected[..], &encoded[..]);
82
83 Ok(())
84 }
85}