#![no_std]
#![forbid(unsafe_code)]
#![deny(missing_docs)]
extern crate alloc;
pub mod isal;
#[cfg(doctest)]
#[doc = include_str!("../../../README.md")]
pub struct ReadmeDoctests;
pub use rusty_erasure_core::{
CodeError, Coder, DecodePlan, Matrix, MatrixError, RecoverError, gf, kernel, matrix, tables,
};
pub mod raid {
pub use rusty_erasure_core::raid::{PqMismatch, PqParity, pq_check, xor_check};
use rusty_erasure_core::{error::CodeError, raid as core_raid};
pub fn xor_gen(sources: &[&[u8]], parity: &mut [u8]) -> Result<(), CodeError> {
#[cfg(feature = "accel")]
if let Some((xor, _)) = rusty_erasure_accel::raid_kernels() {
if sources.len() >= 2 && sources.iter().all(|s| s.len() == parity.len()) {
xor(sources, parity);
return Ok(());
}
}
core_raid::xor_gen(sources, parity)
}
pub fn pq_gen(sources: &[&[u8]], p: &mut [u8], q: &mut [u8]) -> Result<(), CodeError> {
#[cfg(feature = "accel")]
if let Some((_, pq)) = rusty_erasure_accel::raid_kernels()
&& sources.len() >= 2
&& p.len() == q.len()
&& sources.iter().all(|s| s.len() == p.len())
{
pq(sources, p, q);
return Ok(());
}
core_raid::pq_gen(sources, p, q)
}
}
pub fn best_kernels() -> kernel::Kernels {
#[cfg(feature = "accel")]
if let Some(k) = rusty_erasure_accel::kernels() {
return k;
}
kernel::Kernels::scalar()
}
pub fn coder(matrix: Matrix) -> Result<Coder, MatrixError> {
Coder::with_kernels(matrix, best_kernels())
}
pub fn kernels_named(name: &str) -> Option<kernel::Kernels> {
match name {
"auto" => Some(best_kernels()),
"scalar" => Some(kernel::Kernels::scalar()),
#[cfg(feature = "accel")]
"ssse3" => rusty_erasure_accel::x86::kernels_at(rusty_erasure_accel::x86::Level::Ssse3),
#[cfg(feature = "accel")]
"avx2" => rusty_erasure_accel::x86::kernels_at(rusty_erasure_accel::x86::Level::Avx2),
#[cfg(feature = "accel")]
"gfni" => rusty_erasure_accel::x86::kernels_at(rusty_erasure_accel::x86::Level::Gfni),
#[cfg(feature = "accel")]
"neon" => rusty_erasure_accel::aarch64::kernels(),
#[cfg(feature = "accel")]
"simd128" => rusty_erasure_accel::wasm::kernels(),
_ => None,
}
}
pub mod compat {
use rusty_erasure_core::error::MatrixError;
use rusty_erasure_core::{Matrix, gf};
pub fn reed_solomon_erasure_matrix(k: usize, p: usize) -> Result<Matrix, MatrixError> {
let n = k + p;
if k == 0 || p == 0 || n > 256 {
return Err(MatrixError::Dimensions { k, p });
}
let mut v = alloc::vec![0u8; n * k];
for r in 0..n {
let mut acc: u8 = 1; for c in 0..k {
v[r * k + c] = acc;
acc = gf::mul(acc, r as u8);
}
}
let vand = Matrix::from_bytes(n, k, v)?;
let top = vand.select_rows(&(0..k).collect::<alloc::vec::Vec<_>>())?;
vand.multiply(&top.invert()?)
}
}
pub mod census {
use core::sync::atomic::Ordering;
#[derive(Debug, Clone, Copy)]
pub struct Census {
pub scalar_bytes: u64,
pub accel_bytes: u64,
}
impl Census {
pub fn accel_percent(&self) -> Option<f64> {
let total = self.scalar_bytes + self.accel_bytes;
if total == 0 {
None
} else {
Some(self.accel_bytes as f64 * 100.0 / total as f64)
}
}
}
pub fn read() -> Census {
Census {
scalar_bytes: crate::kernel::SCALAR_CENSUS_BYTES.load(Ordering::Relaxed),
accel_bytes: {
#[cfg(feature = "accel")]
{
rusty_erasure_accel::x86::ACCEL_CENSUS_BYTES.load(Ordering::Relaxed)
}
#[cfg(not(feature = "accel"))]
{
0
}
},
}
}
}