#![allow(dead_code)]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(
all(feature = "simd-vsx", target_arch = "powerpc64"),
feature(stdarch_powerpc, powerpc_target_feature)
)]
#[cfg(test)]
#[macro_use]
extern crate quickcheck;
#[cfg(test)]
extern crate rand;
extern crate smallvec;
#[cfg(any(
feature = "simd-neon",
feature = "simd-ssse3",
feature = "simd-avx2",
feature = "simd-avx512",
feature = "simd-gfni",
))]
extern crate libc;
use ::core::iter::FromIterator;
#[macro_use]
mod macros;
mod core;
mod errors;
mod matrix;
#[cfg(test)]
mod tests;
pub mod galois_16;
pub mod galois_8;
pub use crate::errors::Error;
pub use crate::errors::SBSError;
pub use crate::core::CodecFamily;
pub use crate::core::CodecOptions;
#[cfg(feature = "std")]
pub use crate::core::LeopardGf8ProfileStats;
pub use crate::core::LeopardMode;
pub use crate::core::MatrixMode;
#[cfg(feature = "std")]
pub use crate::core::PARALLEL_POLICY_VERSION;
#[cfg(feature = "std")]
pub use crate::core::ParallelDecision;
#[cfg(feature = "std")]
pub use crate::core::ParallelPolicy;
#[cfg(feature = "std")]
pub use crate::core::ReconstructionCacheAnalysis;
#[cfg(feature = "std")]
pub use crate::core::ReconstructionCacheStats;
pub use crate::core::ReedSolomon;
#[cfg(feature = "std")]
pub use crate::core::RuntimeProfileStats;
pub use crate::core::ShardByShard;
pub use crate::core::VerifyWorkspace;
#[cfg(feature = "std")]
pub use crate::core::stream;
pub use crate::core::{LEOPARD_SHARD_MULTIPLE, leopard_aligned_shard_len};
#[cfg(feature = "std")]
pub fn leopard_gf8_profile_stats() -> LeopardGf8ProfileStats {
crate::core::leopard_gf8_profile_stats()
}
#[cfg(feature = "std")]
pub fn reset_leopard_gf8_profile_stats() {
crate::core::reset_leopard_gf8_profile_stats()
}
#[cfg(not(feature = "std"))]
use libm::log2f as log2;
#[cfg(feature = "std")]
fn log2(n: f32) -> f32 {
n.log2()
}
pub trait Field: Sized {
const ORDER: usize;
type Elem: Default + Clone + Copy + PartialEq + ::core::fmt::Debug;
fn add(a: Self::Elem, b: Self::Elem) -> Self::Elem;
fn mul(a: Self::Elem, b: Self::Elem) -> Self::Elem;
fn div(a: Self::Elem, b: Self::Elem) -> Self::Elem;
fn exp(a: Self::Elem, n: usize) -> Self::Elem;
fn zero() -> Self::Elem;
fn one() -> Self::Elem;
fn nth_internal(n: usize) -> Self::Elem;
fn nth_checked(n: usize) -> Option<Self::Elem> {
if n >= Self::ORDER {
None
} else {
Some(Self::nth_internal(n))
}
}
fn nth(n: usize) -> Self::Elem {
Self::nth_checked(n).unwrap_or_else(|| {
debug_assert!(
false,
"Field::nth received out-of-range index: {} for GF(2^{}) order {}",
n,
log2(Self::ORDER as f32) as usize,
Self::ORDER
);
let fallback_n = n % Self::ORDER.max(1);
Self::nth_internal(fallback_n)
})
}
fn mul_slice(elem: Self::Elem, input: &[Self::Elem], out: &mut [Self::Elem]) {
assert_eq!(input.len(), out.len());
for (i, o) in input.iter().zip(out) {
*o = Self::mul(elem, *i)
}
}
fn mul_slice_add(elem: Self::Elem, input: &[Self::Elem], out: &mut [Self::Elem]) {
assert_eq!(input.len(), out.len());
for (i, o) in input.iter().zip(out) {
*o = Self::add(*o, Self::mul(elem, *i))
}
}
}
pub type ReconstructInitResult<'a, F> =
Result<&'a mut [<F as Field>::Elem], Result<&'a mut [<F as Field>::Elem], Error>>;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ShardSlot<T> {
data: T,
present: bool,
}
impl<T> ShardSlot<T> {
pub fn new_present(data: T) -> Self {
Self {
data,
present: true,
}
}
pub fn new_missing(data: T) -> Self {
Self {
data,
present: false,
}
}
pub fn with_present(data: T, present: bool) -> Self {
Self { data, present }
}
pub fn is_present(&self) -> bool {
self.present
}
pub fn mark_present(&mut self) {
self.present = true;
}
pub fn mark_missing(&mut self) {
self.present = false;
}
pub fn as_inner(&self) -> &T {
&self.data
}
pub fn as_inner_mut(&mut self) -> &mut T {
&mut self.data
}
pub fn into_inner(self) -> T {
self.data
}
}
pub trait ReconstructShard<F: Field> {
fn len(&self) -> Option<usize>;
fn is_empty(&self) -> bool {
self.len().is_none()
}
fn get(&mut self) -> Option<&mut [F::Elem]>;
fn get_or_initialize(&mut self, len: usize) -> ReconstructInitResult<'_, F>;
}
impl<F: Field, T: AsRef<[F::Elem]> + AsMut<[F::Elem]> + FromIterator<F::Elem>> ReconstructShard<F>
for Option<T>
{
fn len(&self) -> Option<usize> {
self.as_ref().map(|x| x.as_ref().len())
}
fn get(&mut self) -> Option<&mut [F::Elem]> {
self.as_mut().map(|x| x.as_mut())
}
fn get_or_initialize(&mut self, len: usize) -> ReconstructInitResult<'_, F> {
let is_some = self.is_some();
let x = self
.get_or_insert_with(|| ::core::iter::repeat_n(F::zero(), len).collect())
.as_mut();
if is_some { Ok(x) } else { Err(Ok(x)) }
}
}
impl<F: Field, T: AsRef<[F::Elem]> + AsMut<[F::Elem]>> ReconstructShard<F> for (T, bool) {
fn len(&self) -> Option<usize> {
if !self.1 {
None
} else {
Some(self.0.as_ref().len())
}
}
fn get(&mut self) -> Option<&mut [F::Elem]> {
if !self.1 { None } else { Some(self.0.as_mut()) }
}
fn get_or_initialize(&mut self, len: usize) -> ReconstructInitResult<'_, F> {
let x = self.0.as_mut();
if x.len() == len {
if self.1 {
Ok(x)
} else {
self.1 = true;
Err(Ok(x))
}
} else {
Err(Err(Error::IncorrectShardSize))
}
}
}
impl<F: Field, T: AsRef<[F::Elem]> + AsMut<[F::Elem]>> ReconstructShard<F> for ShardSlot<T> {
fn len(&self) -> Option<usize> {
if self.present {
Some(self.data.as_ref().len())
} else {
None
}
}
fn get(&mut self) -> Option<&mut [F::Elem]> {
if self.present {
Some(self.data.as_mut())
} else {
None
}
}
fn get_or_initialize(&mut self, len: usize) -> ReconstructInitResult<'_, F> {
let x = self.data.as_mut();
if x.len() == len {
if self.present {
Ok(x)
} else {
self.present = true;
Err(Ok(x))
}
} else {
Err(Err(Error::IncorrectShardSize))
}
}
}