use crate::finite_field::ANTILOG_TABLE;
use crate::{Polynomial, RSConstructorError, ReedSolomon};
impl ReedSolomon {
pub fn compute_syndromes_detached(
parity: &[u8],
data: &[u8],
) -> Result<Polynomial, RSConstructorError> {
Self::check_detached_parity(parity)?;
let syndromes = (0..parity.len())
.map(|i| {
Polynomial::eval_coefficient_slices_at(&[parity, data], ANTILOG_TABLE[i + 1].get())
})
.collect();
Ok(syndromes)
}
}
#[cfg(test)]
mod tests {
use ps_buffer::ToBuffer;
use crate::{RSConstructorError, ReedSolomon, MAX_PARITY_BYTES};
type TestError = Box<dyn std::error::Error>;
#[test]
fn test_compute_syndromes_detached_no_errors() -> Result<(), TestError> {
let rs = ReedSolomon::new(3)?;
let message = b"Detached".to_buffer()?;
let parity = rs.generate_parity(&message)?;
let syndromes = ReedSolomon::compute_syndromes_detached(&parity, &message)?;
assert!(syndromes.is_zero());
Ok(())
}
#[test]
fn test_compute_syndromes_detached_with_errors() -> Result<(), TestError> {
let rs = ReedSolomon::new(3)?;
let message = b"Detached".to_buffer()?;
let parity = rs.generate_parity(&message)?;
let mut corrupted = message.clone()?;
corrupted[2] ^= 2;
let syndromes = ReedSolomon::compute_syndromes_detached(&parity, &corrupted)?;
assert!(syndromes.iter().any(|&s| s != 0));
Ok(())
}
#[test]
fn test_compute_syndromes_detached_empty_data() -> Result<(), TestError> {
let rs = ReedSolomon::new(2)?;
let parity = rs.generate_parity(&[])?;
let syndromes = ReedSolomon::compute_syndromes_detached(&parity, &[])?;
assert_eq!(syndromes.degree(), 0);
assert!(syndromes.is_zero());
Ok(())
}
#[test]
fn test_compute_syndromes_detached_max_parity_bytes() -> Result<(), TestError> {
let parity = [0u8; MAX_PARITY_BYTES as usize];
let syndromes = ReedSolomon::compute_syndromes_detached(&parity, &[])?;
assert!(syndromes.is_zero());
Ok(())
}
#[test]
fn test_compute_syndromes_detached_rejects_odd_parity_length() {
for parity_len in [1usize, 3, 125] {
let parity = vec![0u8; parity_len];
assert_eq!(
ReedSolomon::compute_syndromes_detached(&parity, &[]),
Err(RSConstructorError::OddParityLength(parity_len))
);
}
}
#[test]
fn test_compute_syndromes_detached_oversized_wins_over_odd() {
let parity = [0u8; 127];
assert_eq!(
ReedSolomon::compute_syndromes_detached(&parity, &[]),
Err(RSConstructorError::ParityTooHigh)
);
}
#[test]
fn test_compute_syndromes_detached_rejects_oversized_parity() {
for parity_len in [127usize, 256, 300] {
let parity = vec![0u8; parity_len];
assert_eq!(
ReedSolomon::compute_syndromes_detached(&parity, &[]),
Err(RSConstructorError::ParityTooHigh)
);
}
}
}