use crate::Field;
use crate::errors::{Error, SBSError};
use super::ReedSolomon;
#[derive(PartialEq, Debug)]
pub struct ShardByShard<'a, F: 'a + Field> {
codec: &'a ReedSolomon<F>,
cur_input: usize,
}
impl<'a, F: 'a + Field> ShardByShard<'a, F> {
pub fn new(codec: &'a ReedSolomon<F>) -> ShardByShard<'a, F> {
ShardByShard {
codec,
cur_input: 0,
}
}
pub fn parity_ready(&self) -> bool {
self.cur_input == self.codec.data_shard_count
}
pub fn reset(&mut self) -> Result<(), SBSError> {
if self.cur_input > 0 && !self.parity_ready() {
return Err(SBSError::LeftoverShards);
}
self.cur_input = 0;
Ok(())
}
pub fn reset_force(&mut self) {
self.cur_input = 0;
}
pub fn cur_input_index(&self) -> usize {
self.cur_input
}
fn return_ok_and_incre_cur_input(&mut self) -> Result<(), SBSError> {
self.cur_input += 1;
Ok(())
}
fn sbs_encode_checks<U: AsRef<[F::Elem]> + AsMut<[F::Elem]>>(
&mut self,
slices: &mut [U],
) -> Result<(), SBSError> {
let internal_checks = |codec: &ReedSolomon<F>, data: &mut [U]| -> Result<(), Error> {
check_piece_count!(all => codec, data);
check_slices!(multi => data);
Ok(())
};
if self.parity_ready() {
return Err(SBSError::TooManyCalls);
}
match internal_checks(self.codec, slices) {
Ok(()) => Ok(()),
Err(e) => Err(SBSError::RSError(e)),
}
}
fn sbs_encode_sep_checks<T: AsRef<[F::Elem]>, U: AsRef<[F::Elem]> + AsMut<[F::Elem]>>(
&mut self,
data: &[T],
parity: &mut [U],
) -> Result<(), SBSError> {
let internal_checks =
|codec: &ReedSolomon<F>, data: &[T], parity: &mut [U]| -> Result<(), Error> {
check_piece_count!(data => codec, data);
check_piece_count!(parity => codec, parity);
check_slices!(multi => data, multi => parity);
Ok(())
};
if self.parity_ready() {
return Err(SBSError::TooManyCalls);
}
match internal_checks(self.codec, data, parity) {
Ok(()) => Ok(()),
Err(e) => Err(SBSError::RSError(e)),
}
}
pub fn encode<T, U>(&mut self, mut shards: T) -> Result<(), SBSError>
where
T: AsRef<[U]> + AsMut<[U]>,
U: AsRef<[F::Elem]> + AsMut<[F::Elem]>,
{
let shards = shards.as_mut();
self.sbs_encode_checks(shards)?;
self.codec
.encode_single(self.cur_input, shards)
.map_err(SBSError::RSError)?;
self.return_ok_and_incre_cur_input()
}
pub fn encode_sep<T: AsRef<[F::Elem]>, U: AsRef<[F::Elem]> + AsMut<[F::Elem]>>(
&mut self,
data: &[T],
parity: &mut [U],
) -> Result<(), SBSError> {
self.sbs_encode_sep_checks(data, parity)?;
self.codec
.encode_single_sep(self.cur_input, data[self.cur_input].as_ref(), parity)
.map_err(SBSError::RSError)?;
self.return_ok_and_incre_cur_input()
}
}