diff --git a/src/core.rs b/src/core.rs index cde224f..bb15987 100644 --- a/src/core.rs +++ b/src/core.rs @@ -435,14 +435,14 @@ impl ReedSolomon { vandermonde.multiply(&top.invert().unwrap()) } - /// Creates a new instance of Reed-Solomon erasure code encoder/decoder. + /// Cheks the validity of data and parity shard counts. /// /// Returns `Error::TooFewDataShards` if `data_shards == 0`. /// /// Returns `Error::TooFewParityShards` if `parity_shards == 0`. /// /// Returns `Error::TooManyShards` if `data_shards + parity_shards > F::ORDER`. - pub fn new(data_shards: usize, parity_shards: usize) -> Result, Error> { + fn check_shard_count(data_shards: usize, parity_shards: usize) -> Result<(), Error> { if data_shards == 0 { return Err(Error::TooFewDataShards); } @@ -452,6 +452,18 @@ impl ReedSolomon { if data_shards + parity_shards > F::ORDER { return Err(Error::TooManyShards); } + Ok(()) + } + + /// Creates a new instance of Reed-Solomon erasure code encoder/decoder. + /// + /// Returns `Error::TooFewDataShards` if `data_shards == 0`. + /// + /// Returns `Error::TooFewParityShards` if `parity_shards == 0`. + /// + /// Returns `Error::TooManyShards` if `data_shards + parity_shards > F::ORDER`. + pub fn new(data_shards: usize, parity_shards: usize) -> Result, Error> { + Self::check_shard_count(data_shards, parity_shards)?; let total_shards = data_shards + parity_shards; @@ -466,6 +478,42 @@ impl ReedSolomon { }) } + /// Creates a new instance of Reed-Solomon erasure code encoder/decoder with an externally built matrix. + /// + /// Returns `Error::TooFewDataShards` if `data_shards == 0`. + /// + /// Returns `Error::TooFewParityShards` if `parity_shards == 0`. + /// + /// Returns `Error::TooManyShards` if `data_shards + parity_shards > F::ORDER`. + /// + /// Returns `Error::IncorrectShardSize` if `data_shards != matrix.col_count()`. + /// + /// Returns `Error::IncorrectShardSize` if `data_shards + parity_shards != matrix.row_count()`. + pub fn new_with_matrix( + data_shards: usize, + parity_shards: usize, + matrix: Matrix, + ) -> Result, Error> { + Self::check_shard_count(data_shards, parity_shards)?; + + let total_shards = data_shards + parity_shards; + + if data_shards != matrix.col_count() { + return Err(Error::IncorrectShardSize); + } + if total_shards != matrix.row_count() { + return Err(Error::IncorrectShardSize); + } + + Ok(ReedSolomon { + data_shard_count: data_shards, + parity_shard_count: parity_shards, + total_shard_count: total_shards, + matrix, + data_decode_matrix_cache: Mutex::new(LruCache::new(DATA_DECODE_MATRIX_CACHE_CAPACITY)), + }) + } + pub fn data_shard_count(&self) -> usize { self.data_shard_count } diff --git a/src/lib.rs b/src/lib.rs index 0ba04ae..1bcbf1d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,13 +30,13 @@ mod macros; mod core; mod errors; -mod matrix; #[cfg(test)] mod tests; pub mod galois_16; pub mod galois_8; +pub mod matrix; pub use crate::errors::Error; pub use crate::errors::SBSError; diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 488443b..3c1508c 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -5,7 +5,7 @@ extern crate alloc; use alloc::vec; use alloc::vec::Vec; -use super::{galois_8, Error, SBSError}; +use super::{galois_8, matrix, Error, SBSError}; use rand::{self, thread_rng, Rng}; mod galois_16; @@ -2617,3 +2617,48 @@ fn test_encode_single_error_handling() { ); } } + +#[test] +fn test_new_with_matrix_invalid_data_shards() { + let matrix = matrix::Matrix::new_with_data(vec![ + vec![1, 0, 0], + vec![0, 1, 0], + vec![0, 0, 1], + vec![1, 1, 1], + vec![4, 2, 1], + ]); + + assert_eq!( + Error::IncorrectShardSize, + ReedSolomon::new_with_matrix(10, 2, matrix).unwrap_err() + ); +} + +#[test] +fn test_new_with_matrix_invalid_parity_shards() { + let matrix = matrix::Matrix::new_with_data(vec![ + vec![1, 0, 0], + vec![0, 1, 0], + vec![0, 0, 1], + vec![1, 1, 1], + vec![4, 2, 1], + ]); + + assert_eq!( + Error::IncorrectShardSize, + ReedSolomon::new_with_matrix(3, 1, matrix).unwrap_err() + ); +} + +#[test] +fn test_new_with_matrix_ok() { + let matrix = matrix::Matrix::new_with_data(vec![ + vec![1, 0, 0], + vec![0, 1, 0], + vec![0, 0, 1], + vec![1, 1, 1], + vec![4, 2, 1], + ]); + + assert!(ReedSolomon::new_with_matrix(3, 2, matrix).is_ok()); +}