diff --git a/Cargo.toml b/Cargo.toml index 48132ee..ad87981 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,9 +8,15 @@ license = "MIT" keywords = ["cryptography", "ecc", "bch", "no_std"] authors = ["Mike Lubinets "] version = "0.2.1" +edition = "2021" + +[dependencies] +heapless = "0.8.0" [dev-dependencies] -rustc-serialize = "0.3" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" [features] unsafe_indexing = [] +decoder = [] diff --git a/examples/bandwidth.rs b/examples/bandwidth.rs index 5ac7627..61d2b86 100644 --- a/examples/bandwidth.rs +++ b/examples/bandwidth.rs @@ -1,5 +1,12 @@ +extern crate serde; +extern crate serde_json; extern crate reed_solomon; -extern crate rustc_serialize; + +use std::thread; +use std::time::Duration; +use std::sync::mpsc; + +use serde::{Serialize}; use reed_solomon::Encoder; use reed_solomon::Decoder; @@ -24,19 +31,15 @@ impl Iterator for Generator { } } -use std::thread; -use std::time::Duration; -use std::sync::mpsc; - // Returns MB/s -fn encoder_bandwidth(data_len: usize, ecc_len: usize) -> f32 { +fn encoder_bandwidth(data_len: usize, ecc_len: usize) -> f32 { // Measure encoding bandwidth let (tx, thr_rx) = mpsc::channel(); let (thr_tx, rx) = mpsc::channel(); thread::spawn(move || { let generator = Generator::new(); - let encoder = Encoder::new(ecc_len); + let mut encoder = Encoder::<33>::new(ecc_len); let buffer: Vec = generator.take(data_len).collect(); let mut bytes = 0; @@ -64,19 +67,21 @@ fn decoder_bandwidth(data_len: usize, ecc_len: usize, errors: usize) -> f32 { thread::spawn(move || { let generator = Generator::new(); - let encoder = Encoder::new(ecc_len); + let mut encoder = Encoder::<33>::new(ecc_len); let decoder = Decoder::new(ecc_len); let buffer: Vec = generator.take(data_len).collect(); let mut encoded = encoder.encode(&buffer); - for x in encoded.iter_mut().take(errors) { + let mut message = buffer.clone(); + message.extend_from_slice(&encoded[..]); + for x in message.iter_mut().take(errors) { *x = 0; } let mut bytes = 0; while thr_rx.try_recv().is_err() { - if decoder.is_corrupted(&encoded) { - decoder.correct(&mut encoded, None).unwrap(); + if decoder.is_corrupted(&message) { + decoder.correct(&mut message, None).unwrap(); } bytes += data_len; } @@ -92,7 +97,7 @@ fn decoder_bandwidth(data_len: usize, ecc_len: usize, errors: usize) -> f32 { kbytes / 1024.0 } -#[derive(RustcEncodable)] +#[derive(Serialize)] struct BenchResult { data_len: usize, ecc_len: usize, @@ -100,12 +105,12 @@ struct BenchResult { decoder: Vec } -#[derive(RustcEncodable)] +#[derive(Serialize)] struct EncoderResult { bandwidth: f32 } -#[derive(RustcEncodable)] +#[derive(Serialize)] struct DecoderResult { errors: usize, bandwidth: f32 @@ -129,6 +134,6 @@ fn main() { } }).collect(); - let json = rustc_serialize::json::encode(&results).unwrap(); + let json = serde_json::to_string(&results).unwrap(); println!("{}", json); } diff --git a/examples/helloworld.rs b/examples/helloworld.rs index 02881a3..77249e8 100644 --- a/examples/helloworld.rs +++ b/examples/helloworld.rs @@ -10,14 +10,16 @@ fn main() { let ecc_len = 8; // Create encoder and decoder with - let enc = Encoder::new(ecc_len); + let mut enc = Encoder::<9>::new(ecc_len); let dec = Decoder::new(ecc_len); // Encode data let encoded = enc.encode(&data[..]); // Simulate some transmission errors - let mut corrupted = *encoded; + let mut corrupted = Vec::new(); + corrupted.extend_from_slice(&data[..]); + corrupted.extend_from_slice(&encoded[..]); for x in corrupted.iter_mut().take(4) { *x = 0x0; } @@ -31,7 +33,7 @@ fn main() { println!("message: {:?}", orig_str); println!("original data: {:?}", data); - println!("error correction code: {:?}", encoded.ecc()); + println!("error correction code: {:?}", encoded); println!("corrupted: {:?}", corrupted); println!("repaired: {:?}", recv_str); -} \ No newline at end of file +} diff --git a/src/buffer.rs b/src/buffer.rs index 0609a26..78f444e 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -1,6 +1,7 @@ -use ::gf::poly::Polynom; +use crate::gf::poly::Polynom; use core::ops::{Deref, DerefMut}; + /// Buffer for block encoded data /// # Example /// ```rust diff --git a/src/decoder.rs b/src/decoder.rs index 6f730df..f5e97b6 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -1,8 +1,8 @@ use core; -use ::gf::poly_math::*; -use ::gf::poly::Polynom; -use ::buffer::Buffer; -use ::gf; +use crate::gf::poly_math::*; +use crate::gf::poly::Polynom; +use crate::gf; +use crate::buffer::Buffer; /// Decoder error #[derive(Debug, Copy, Clone)] @@ -41,21 +41,23 @@ impl Decoder { /// use reed_solomon::Decoder; /// /// // Create encoder and decoder - /// let encoder = Encoder::new(4); + /// let mut encoder = Encoder::<5>::new(4); /// let decoder = Decoder::new(4); /// /// // Encode message /// let mut encoded = encoder.encode(&[1, 2, 3, 4]); + /// let mut message = vec![1, 2, 3, 4]; + /// message.extend_from_slice(&encoded[..]); /// /// // Corrupt message - /// encoded[2] = 1; - /// encoded[3] = 2; + /// message[2] = 1; + /// message[3] = 2; /// /// // Let's assume it's known that `encoded[3]` is an error /// let known_erasures = [3]; /// /// // Decode and correct message, - /// let corrected = decoder.correct(&mut encoded, Some(&known_erasures)).unwrap(); + /// let corrected = decoder.correct(&mut message, Some(&known_erasures)).unwrap(); /// /// // Check results /// assert_eq!(&[1, 2, 3, 4], corrected.data()) @@ -89,8 +91,8 @@ impl Decoder { } let fsynd = self.forney_syndromes(&synd, erase_pos, msg.len()); - let err_loc = try!(self.find_error_locator(&fsynd, None, erase_pos.len())); - let mut err_pos = try!(self.find_errors(&err_loc.reverse(), msg.len())); + let err_loc = self.find_error_locator(&fsynd, None, erase_pos.len())?; + let mut err_pos = self.find_errors(&err_loc.reverse(), msg.len())?; // Append erase_pos to err_pos for x in erase_pos.iter() { @@ -115,21 +117,22 @@ impl Decoder { /// use reed_solomon::Decoder; /// /// // Create encoder and decoder - /// let encoder = Encoder::new(4); + /// let mut encoder = Encoder::<5>::new(4); /// let decoder = Decoder::new(4); /// /// // Encode message /// let mut encoded = encoder.encode(&[1, 2, 3, 4]); - /// + /// let mut message = vec![1, 2, 3, 4]; + /// message.extend_from_slice(&encoded[..]); /// // Corrupt message - /// encoded[2] = 1; - /// encoded[3] = 2; + /// message[2] = 1; + /// message[3] = 2; /// /// // Let's assume it's known that `encoded[3]` is an error /// let known_erasures = [3]; /// /// // Decode and correct message, - /// let corrected = decoder.correct(&mut encoded, Some(&known_erasures)).unwrap(); + /// let corrected = decoder.correct(&mut message, Some(&known_erasures)).unwrap(); /// /// // Check results /// assert_eq!(&[1, 2, 3, 4], corrected.data()) @@ -149,19 +152,21 @@ impl Decoder { /// use reed_solomon::Decoder; /// /// // Create encoder and decoder - /// let encoder = Encoder::new(4); + /// let mut encoder = Encoder::<5>::new(4); /// let decoder = Decoder::new(4); /// /// // Encode message - /// let mut encoded = encoder.encode(&[1, 2, 3, 4]); + /// let encoded = encoder.encode(&[1, 2, 3, 4]); + /// let mut message = vec![1, 2, 3, 4]; + /// message.extend_from_slice(&encoded[..]); /// - /// assert_eq!(decoder.is_corrupted(&encoded), false); + /// assert_eq!(decoder.is_corrupted(&message), false); /// /// // Corrupt message - /// encoded[2] = 1; - /// encoded[3] = 2; + /// message[2] = 1; + /// message[3] = 2; /// - /// assert_eq!(decoder.is_corrupted(&encoded), true); + /// assert_eq!(decoder.is_corrupted(&message), true); /// ``` pub fn is_corrupted(&self, msg: &[u8]) -> bool { (0..self.ecc_len).any(|x| msg.eval(gf::pow(2, x as i32)) != 0) @@ -351,32 +356,38 @@ impl Decoder { #[cfg(test)] mod tests { + use std::vec::Vec; use super::*; - use ::Encoder; + use crate::Encoder; #[test] fn calc_syndromes() { let px = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - let mut encoded = Encoder::new(8).encode(&px[..]); + let mut encoded = Encoder::<9>::new(8).encode(&px[..]); + let mut message = Vec::from(&px[..]); + message.extend_from_slice(&encoded[..]); - assert_eq!([0; 9], *Decoder::new(8).calc_syndromes(&encoded)); + assert_eq!([0; 9], *Decoder::new(8).calc_syndromes(&message)); - encoded[5] = 1; + message[5] = 1; assert_eq!([0, 7, 162, 172, 245, 176, 71, 58, 180], - *Decoder::new(8).calc_syndromes(&encoded)); + *Decoder::new(8).calc_syndromes(&message)); } #[test] fn is_corrupted() { let px = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - let mut encoded = Encoder::new(8).encode(&px[..]); + let mut encoded = Encoder::<9>::new(8).encode(&px[..]); + let mut message = Vec::new(); + message.extend_from_slice(&px[..]); + message.extend_from_slice(&encoded[..]); - assert_eq!(false, Decoder::new(8).is_corrupted(&encoded)); + assert_eq!(false, Decoder::new(8).is_corrupted(&message)); - encoded[5] = 1; + message[5] = 1; - assert_eq!(true, Decoder::new(8).is_corrupted(&encoded)); + assert_eq!(true, Decoder::new(8).is_corrupted(&message)); } #[test] @@ -410,15 +421,17 @@ mod tests { #[test] fn error_count() { let msg = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - let encoder = Encoder::new(10); + let mut encoder = Encoder::<11>::new(10); let encoded = encoder.encode(&msg[..]); - let mut errd = *encoded; + let mut full_message = Vec::new(); + full_message.extend_from_slice(&msg[..]); + full_message.extend_from_slice(&encoded[..]); - errd[0] = 255; - errd[3] = 255; + full_message[0] = 255; + full_message[3] = 255; - let (_correct,err) = Decoder::new(10).correct_err_count(&errd, None).unwrap(); + let (_correct,err) = Decoder::new(10).correct_err_count(&full_message, None).unwrap(); assert_eq!(err, 2); } diff --git a/src/encoder.rs b/src/encoder.rs index 94bd457..d6eb2d5 100644 --- a/src/encoder.rs +++ b/src/encoder.rs @@ -1,25 +1,53 @@ -use ::gf::poly_math::*; -use ::gf::poly::Polynom; -use ::buffer::Buffer; -use ::gf; +use core::convert::TryInto; +use super::gf::poly_math::*; +use super::gf; +use heapless::Vec; /// Reed-Solomon BCH encoder #[derive(Debug)] -pub struct Encoder { - generator: Polynom, +pub struct Encoder { + generator: [u8; ECC_BYTE_COUNT_STORE], + lgenerator: [u8; ECC_BYTE_COUNT_STORE], + scratch_space: Vec, + bytes_processed: u8, } -impl Encoder { +impl Encoder { + const fn make_lgenerator(generator: &[u8; ECC_BYTE_COUNT_STORE]) -> [u8; ECC_BYTE_COUNT_STORE] { + let mut lgen = [0u8; ECC_BYTE_COUNT_STORE]; + let mut i = 0; + while i < generator.len() { + lgen[i] = gf::LOG[generator[i] as usize]; + i += 1; + } + lgen + } + /// Constructs a new `Encoder` and calculates generator polynomial of given `ecc_len`. /// /// # Example /// ```rust /// use reed_solomon::Encoder; /// - /// let encoder = Encoder::new(8); + /// let encoder = Encoder::<9>::new(8); /// ``` pub fn new(ecc_len: usize) -> Self { - Encoder { generator: generator_poly(ecc_len) } + debug_assert!(ecc_len == ECC_BYTE_COUNT_STORE - 1, "ECC length must be ECC_BYTE_COUNT_STORE - 1"); + let generator: [u8; ECC_BYTE_COUNT_STORE] = generator_poly(ecc_len).try_into().unwrap(); + + Self::new_with_precomputed_generator(&generator) + } + + + // generator_poly should be called to produce an array to be passed into this function + // The array should be ecc_len + 1 bytes long + pub const fn new_with_precomputed_generator(generator: &[u8; ECC_BYTE_COUNT_STORE]) -> Self { + Self { + lgenerator: Self::make_lgenerator(generator), + generator: *generator, + scratch_space: Vec::new(), + bytes_processed: 0, + } } /// Encodes passed `&[u8]` slice and returns `Buffer` with result and `ecc` offset. @@ -29,87 +57,193 @@ impl Encoder { /// use reed_solomon::Encoder; /// /// let data = "Hello World".as_bytes(); - /// let encoder = Encoder::new(8); + /// let mut encoder = Encoder::<9>::new(8); /// /// let encoded = encoder.encode(&data); /// - /// println!("whole: {:?}", &encoded[..]); - /// println!("data: {:?}", encoded.data()); - /// println!("ecc: {:?}", encoded.ecc()); + /// println!("ecc: {:?}", encoded); /// ``` - pub fn encode(&self, data: &[u8]) -> Buffer { - let mut data_out = Polynom::from(data); - let data_len = data.len(); - - data_out.set_length(data_len + self.generator.len() - 1); - - let gen = self.generator; - let mut lgen = Polynom::with_length(self.generator.len()); - for (i, gen_i) in gen.iter().enumerate() { - uncheck_mut!(lgen[i]) = gf::LOG[*gen_i as usize]; - } - - for i in 0..data_len { - let coef = uncheck!(data_out[i]); - if coef != 0 { - let lcoef = gf::LOG[coef as usize] as usize; - for j in 1..gen.len() { - uncheck_mut!(data_out[i + j]) ^= gf::EXP[(lcoef + lgen[j] as usize)]; - } - } + pub fn encode(&mut self, data: &[u8]) -> Vec { + debug_assert!(data.len() < 256 - self.generator.len(), "Data isnt a single chunk long or less"); + let mut ecc = Vec::::new(); + for byte in data.iter() { + ecc = self.encode_single(*byte); + } + if let Ok(ecc) = self.finalize() { + ecc + } else { + ecc + } + } + + pub fn encode_single(&mut self, data: u8) -> Vec { + //First fill up scratch space + if self.scratch_space.len() < self.generator.len() { + unsafe { self.scratch_space.push(data).unwrap_unchecked() }; + self.bytes_processed += 1; + return unsafe { Vec::from_slice(&[data]).unwrap_unchecked() }; } - data_out[..data_len].copy_from_slice(data); - Buffer::from_polynom(data_out, data_len) + self.run_encoding_round(); + + self.scratch_space.rotate_left(1); + self.scratch_space[self.generator.len() - 1] = data; + + self.bytes_processed += 1; + if self.bytes_processed == (256 - self.generator.len()) as u8 { + let mut ecc = unsafe { self.finalize().unwrap_unchecked() }; + unsafe { ecc.insert(0, data).unwrap_unchecked() }; + return ecc; + } + + unsafe { Vec::from_slice(&[data]).unwrap_unchecked() } + } + + // Errors if nothing in scratch space + pub fn finalize(&mut self) -> Result, ()> { + if self.scratch_space.len() == 0 { + return Err(()); + } + + let mut rounds = self.generator.len(); + if self.scratch_space.len() < self.generator.len() { + rounds = self.scratch_space.len(); + unsafe { self.scratch_space.resize(self.generator.len(), 0).unwrap_unchecked() }; + } + + for _ in 0..rounds { + self.run_encoding_round(); + self.scratch_space.rotate_left(1); + self.scratch_space[self.generator.len() - 1] = 0; + } + let mut out = self.scratch_space.clone(); + out.truncate(self.generator.len() - 1); + self.reset(); + Ok(out) + } + + pub fn reset(&mut self) { + self.scratch_space.clear(); + self.bytes_processed = 0; + } + + fn run_encoding_round(&mut self) { + let coef = unsafe { self.scratch_space.get_unchecked(0) }; + if *coef != 0 { + let lcoef = gf::LOG[*coef as usize] as usize; + for j in 1..self.generator.len() { + let scratch_var: &mut u8 = unsafe { &mut self.scratch_space.get_unchecked_mut(j) }; + let lgen_var = *unsafe { self.lgenerator.get_unchecked(j) }; + *scratch_var ^= gf::EXP[(lcoef + lgen_var as usize)]; + } + } } } -fn generator_poly(ecclen: usize) -> Polynom { +fn generator_poly(ecclen: usize) -> [u8; MAX_LEN] { let mut gen = polynom![1]; let mut mm = [1, 0]; - for i in 0..ecclen { + let mut i = 0; + while i < ecclen { mm[1] = gf::pow(2, i as i32); gen = gen.mul(&mm); + i += 1; } - gen + gen[..].try_into().unwrap() } +pub const ENCODE_GEN_2_ECC_BYTES: [u8; 3] = [1, 3, 2]; +pub const ENCODE_GEN_4_ECC_BYTES: [u8; 5] = [1, 15, 54, 120, 64]; +pub const ENCODE_GEN_8_ECC_BYTES: [u8; 9] = [1, 255, 11, 81, 54, 239, 173, 200, 24]; +pub const ENCODE_GEN_16_ECC_BYTES: [u8; 17] = [1, 59, 13, 104, 189, 68, 209, 30, 8, 163, 65, 41, 229, 98, 50, 36, 59]; + #[cfg(test)] mod tests { + use std::vec::Vec; + #[test] fn generator_poly() { - let answers = - [polynom![1, 3, 2], - polynom![1, 15, 54, 120, 64], - polynom![1, 255, 11, 81, 54, 239, 173, 200, 24], - polynom![1, 59, 13, 104, 189, 68, 209, 30, 8, 163, 65, 41, 229, 98, 50, 36, 59], - polynom![1, 116, 64, 52, 174, 54, 126, 16, 194, 162, 33, 33, 157, 176, 197, 225, 12, + assert_eq!([1, 3, 2], super::generator_poly(2)); + assert_eq!([1, 15, 54, 120, 64], super::generator_poly(4)); + assert_eq!([1, 255, 11, 81, 54, 239, 173, 200, 24], super::generator_poly(8)); + assert_eq!([1, 59, 13, 104, 189, 68, 209, 30, 8, 163, 65, 41, 229, 98, 50, 36, 59], super::generator_poly(16)); + assert_eq!([1, 116, 64, 52, 174, 54, 126, 16, 194, 162, 33, 33, 157, 176, 197, 225, 12, 59, 55, 253, 228, 148, 47, 179, 185, 24, 138, 253, 20, 142, 55, 172, 88], - polynom![1, 193, 10, 255, 58, 128, 183, 115, 140, 153, 147, 91, 197, 219, 221, 220, + super::generator_poly(32) + ); + assert_eq!([1, 193, 10, 255, 58, 128, 183, 115, 140, 153, 147, 91, 197, 219, 221, 220, 142, 28, 120, 21, 164, 147, 6, 204, 40, 230, 182, 14, 121, 48, 143, 77, 228, 81, 85, 43, 162, 16, 195, 163, 35, 149, 154, 35, 132, 100, 100, 51, 176, 11, 161, 134, 208, 132, 244, 176, 192, 221, 232, 171, 125, 155, 228, - 242, 245]]; + 242, 245], + super::generator_poly(64) + ); + } - let mut ecclen = 2; - for i in 0..6 { - assert_eq!(*answers[i], *super::generator_poly(ecclen)); - ecclen *= 2; - } + #[test] + fn check_const_generators() { + assert_eq!(super::ENCODE_GEN_2_ECC_BYTES, super::generator_poly::<3>(2)); + assert_eq!(super::ENCODE_GEN_4_ECC_BYTES, super::generator_poly::<5>(4)); + assert_eq!(super::ENCODE_GEN_8_ECC_BYTES, super::generator_poly::<9>(8)); + assert_eq!(super::ENCODE_GEN_16_ECC_BYTES, super::generator_poly::<17>(16)); } #[test] fn encode() { let data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29]; + 22, 23, 24, 25, 26, 27, 28, 29]; let ecc = [99, 26, 219, 193, 9, 94, 186, 143]; - let encoder = super::Encoder::new(ecc.len()); + let mut encoder = super::Encoder::<9>::new(ecc.len()); + let encoded = encoder.encode(&data[..]); + + assert_eq!(ecc, encoded); + + let mut encoder = super::Encoder::<9>::new_with_precomputed_generator(&super::ENCODE_GEN_8_ECC_BYTES); let encoded = encoder.encode(&data[..]); - assert_eq!(data, encoded.data()); - assert_eq!(ecc, encoded.ecc()); + assert_eq!(ecc, encoded); } + #[test] + fn encode_shorter_than_ecc_message() { + let data = [0, 1, 2, 3, 4]; + let ecc = [44, 157, 28, 43, 61, 248, 104, 250, 152, 77]; + + let mut encoder = super::Encoder::<11>::new(ecc.len()); + let encoded = encoder.encode(&data[..]); + + assert_eq!(ecc, encoded); + } + + #[test] + fn encode_large() { + let mut data = [0; 512]; + for i in 0..512 { + data[i] = i as u8; + } + let expected = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 62, 194, 253, 254, 255, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 216, 37, 250, 251, 252, 253, 254, 255, 251, 250 + ]; + let mut result = Vec::new(); + + let mut encoder = super::Encoder::<3>::new(2); + for i in 0..512 { + let encoded = encoder.encode_single(data[i]); + result.extend_from_slice(&encoded[..]); + } + if let Ok(ecc) = encoder.finalize() { + result.extend_from_slice(&ecc[..]); + } + + assert_eq!(expected, *result); + } } diff --git a/src/gf/mod.rs b/src/gf/mod.rs index a7b502d..709d555 100644 --- a/src/gf/mod.rs +++ b/src/gf/mod.rs @@ -39,7 +39,7 @@ pub static EXP: [u8; EXP_SIZE] = [ ]; const LOG_SIZE: usize = 256; -pub static LOG: [u8; LOG_SIZE] = [ +pub const LOG: [u8; LOG_SIZE] = [ 0x0, 0x0, 0x1, 0x19, 0x2, 0x32, 0x1a, 0xc6, 0x3, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, 0x4, 0x64, 0xe0, 0xe, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x8, 0x4c, 0x71, 0x5, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0xf, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, 0x1d, @@ -232,4 +232,4 @@ mod tests { assert_eq!(super::pow(LOG[i], EXP[i] as i32), answers[i]); } } -} \ No newline at end of file +} diff --git a/src/gf/poly.rs b/src/gf/poly.rs index 0d053c3..29f88a8 100644 --- a/src/gf/poly.rs +++ b/src/gf/poly.rs @@ -1,6 +1,6 @@ #[derive(Copy)] pub struct Polynom { - array: [u8; ::POLYNOMIAL_MAX_LENGTH], + array: [u8; crate::POLYNOMIAL_MAX_LENGTH], length: usize, dirty: bool, } @@ -9,7 +9,7 @@ impl Polynom { #[inline] pub fn new() -> Polynom { Polynom { - array: [0; ::POLYNOMIAL_MAX_LENGTH], + array: [0; crate::POLYNOMIAL_MAX_LENGTH], length: 0, dirty: false, } @@ -91,7 +91,7 @@ impl DerefMut for Polynom { impl<'a> From<&'a [u8]> for Polynom { #[inline] fn from(slice: &'a [u8]) -> Polynom { - debug_assert!(slice.len() <= ::POLYNOMIAL_MAX_LENGTH); + debug_assert!(slice.len() <= crate::POLYNOMIAL_MAX_LENGTH); let mut poly = Polynom::with_length(slice.len()); poly[..].copy_from_slice(slice); poly diff --git a/src/gf/poly_math.rs b/src/gf/poly_math.rs index b82c874..726fc8b 100644 --- a/src/gf/poly_math.rs +++ b/src/gf/poly_math.rs @@ -1,6 +1,6 @@ use core::cmp::max; -use ::gf::poly::Polynom; -use ::gf; +use crate::gf::poly::Polynom; +use crate::gf; pub trait Scale { fn scale(&self, x: u8) -> Polynom; diff --git a/src/lib.rs b/src/lib.rs index e8282f8..e2c04b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,14 +16,15 @@ //! let ecc_len = 8; //! //! // Create encoder and decoder with -//! let enc = Encoder::new(ecc_len); +//! let mut enc = Encoder::<9>::new(ecc_len); //! let dec = Decoder::new(ecc_len); //! //! // Encode data //! let encoded = enc.encode(&data[..]); +//! let mut corrupted = Vec::from(data); +//! corrupted.extend_from_slice(&encoded); //! //! // Simulate some transmission errors -//! let mut corrupted = *encoded; //! for i in 0..4 { //! corrupted[i] = 0x0; //! } @@ -37,7 +38,7 @@ //! //! println!("message: {:?}", orig_str); //! println!("original data: {:?}", data); -//! println!("error correction code: {:?}", encoded.ecc()); +//! println!("error correction code: {:?}", encoded); //! println!("corrupted: {:?}", corrupted); //! println!("repaired: {:?}", recv_str); //! } @@ -167,16 +168,23 @@ #![no_std] +#[cfg(test)] +extern crate std; +extern crate heapless; + const POLYNOMIAL_MAX_LENGTH: usize = 256; #[macro_use] mod macros; mod gf; mod encoder; +#[cfg(feature = "decoder")] mod decoder; +#[cfg(feature = "decoder")] mod buffer; -pub use encoder::Encoder; -pub use decoder::Decoder; -pub use decoder::DecoderError; +pub use encoder::*; +#[cfg(feature = "decoder")] +pub use decoder::{Decoder,DecoderError}; +#[cfg(feature = "decoder")] pub use buffer::Buffer; diff --git a/tests/simple.rs b/tests/simple.rs index c3c5f1a..6501445 100644 --- a/tests/simple.rs +++ b/tests/simple.rs @@ -10,14 +10,16 @@ fn helloworld() { let data = b"Hello, World!"; // Create encoder and decoder - let enc = Encoder::new(ECC_LEN); + let mut enc = Encoder::<{ECC_LEN + 1}>::new(ECC_LEN); let dec = Decoder::new(ECC_LEN); // Encode data let encoded = enc.encode(&data[..]); // Simulate some transmission errors - let mut corrupted = *encoded; + let mut corrupted = Vec::new(); + corrupted.extend_from_slice(&data[..]); + corrupted.extend_from_slice(&encoded[..]); for i in 0..4 { corrupted[i] = 0x0; } @@ -33,14 +35,16 @@ fn with_erasures() { let data = b"Hello, World!"; // Create encoder and decoder - let enc = Encoder::new(ECC_LEN); + let mut enc = Encoder::<{ECC_LEN + 1}>::new(ECC_LEN); let dec = Decoder::new(ECC_LEN); // Encode data let encoded = enc.encode(&data[..]); // Simulate some transmission errors - let mut corrupted = *encoded; + let mut corrupted = Vec::new(); + corrupted.extend_from_slice(&data[..]); + corrupted.extend_from_slice(&encoded[..]); for i in 0..4 { corrupted[i] = 0x0; }