//! GF(2¹⁶) Leopard-RS backend (`reed-solomon-simd`). SIMD, O(n log n), up to 65535 //! shards/block — this is what removes the GameStream 255-shard / ~1 Gbps wall. //! Shard length must be even. use super::{validate_block_shape, validate_encode_shape, ErasureCoder, FecError}; use crate::config::FecScheme; pub struct Gf16Coder; impl ErasureCoder for Gf16Coder { fn scheme(&self) -> FecScheme { FecScheme::Gf16 } fn encode(&self, data: &[Vec], recovery_count: usize) -> Result>, FecError> { if recovery_count == 0 { return Ok(Vec::new()); } validate_encode_shape(data)?; let k = data.len(); if data[0].len() % 2 != 0 { return Err(FecError::Config("GF(2^16) shard length must be even")); } reed_solomon_simd::encode(k, recovery_count, data) .map_err(|_| FecError::Backend("gf16 encode")) } fn reconstruct( &self, data_count: usize, recovery_count: usize, received: &mut [Option>], ) -> Result>, FecError> { validate_block_shape(received, data_count, recovery_count)?; let present = received.iter().filter(|s| s.is_some()).count(); if present < data_count { return Err(FecError::TooFewShards { have: present, need: data_count, }); } // Fast path: all originals already present, or FEC disabled. let originals_complete = received[..data_count].iter().all(|s| s.is_some()); if recovery_count == 0 || originals_complete { let mut out = Vec::with_capacity(data_count); for slot in received.iter().take(data_count) { out.push(slot.clone().ok_or(FecError::TooFewShards { have: present, need: data_count, })?); } return Ok(out); } // Hand the decoder the surviving originals and recovery shards, indexed. let original_in: Vec<(usize, &[u8])> = received[..data_count] .iter() .enumerate() .filter_map(|(i, s)| s.as_deref().map(|b| (i, b))) .collect(); let recovery_in: Vec<(usize, &[u8])> = received[data_count..data_count + recovery_count] .iter() .enumerate() .filter_map(|(j, s)| s.as_deref().map(|b| (j, b))) .collect(); let restored = reed_solomon_simd::decode(data_count, recovery_count, original_in, recovery_in) .map_err(|_| FecError::Backend("gf16 decode"))?; // Merge surviving originals with the recovered ones. let mut out: Vec> = Vec::with_capacity(data_count); for (i, slot) in received[..data_count].iter().enumerate() { if let Some(s) = slot { out.push(s.clone()); } else if let Some(s) = restored.get(&i) { out.push(s.clone()); } else { return Err(FecError::Backend("gf16 decode left an original missing")); } } Ok(out) } }