use libc::*;
use std::ptr;
#[repr(C)]
#[allow(dead_code, non_camel_case_types)]
pub enum EcBackendId {
NULL = 0,
JERASURE_RS_VAND = 1,
JERASURE_RS_CAUCHY = 2,
FLAT_XOR_HD = 3,
ISA_L_RS_VAND = 4,
SHSS = 5,
LIBERASURECODE_RS_VAND = 6,
}
#[repr(C)]
pub enum EcChecksumType {
NONE = 1,
CRC32 = 2,
MD5 = 3,
}
#[repr(C)]
pub struct EcArgs {
pub k: c_int,
pub m: c_int,
pub w: c_int,
pub hd: c_int,
pub priv_args: [u64; 5],
pub ct: EcChecksumType,
}
pub type Desc = c_int;
pub type ErrorCode = c_uint;
pub const EBACKENDNOTSUPP: u32 = 200;
pub const EECMETHODNOTIMPL: u32 = 201;
pub const EBACKENDINITERR: u32 = 202;
pub const EBACKENDINUSE: u32 = 203;
pub const EBACKENDNOTAVAIL: u32 = 204;
pub const EBADCHKSUM: u32 = 205;
pub const EINVALIDPARAMS: u32 = 206;
pub const EBADHEADER: u32 = 207;
pub const EINSUFFFRAGS: u32 = 208;
#[link(name = "erasurecode", kind = "static")]
#[link(name = "gf_complete", kind = "static")]
#[link(name = "Jerasure", kind = "static")]
#[link(name = "Xorcode", kind = "static")]
extern "C" {
fn liberasurecode_instance_create(id: EcBackendId, args: *const EcArgs) -> Desc;
fn liberasurecode_instance_destroy(desc: Desc) -> c_int;
fn liberasurecode_encode(
desc: Desc,
orig_data: *const u8,
orig_data_size: u64,
encoded_data: *mut *mut *mut u8,
encoded_parity: *mut *mut *mut u8,
fragment_len: *mut u64,
) -> c_int;
fn liberasurecode_encode_cleanup(
desc: Desc,
encoded_data: *mut *mut u8,
encoded_parity: *mut *mut u8,
) -> c_int;
fn liberasurecode_decode(
desc: Desc,
fragments: *const *const u8,
num_fragments: c_int,
fragment_len: u64,
force_metadata_checks: c_int,
out_data: *mut *mut u8,
out_data_len: *mut u64,
) -> c_int;
fn liberasurecode_decode_cleanup(desc: Desc, data: *mut u8) -> c_int;
fn liberasurecode_reconstruct_fragment(
desc: Desc,
available_fragments: *const *const u8,
num_fragments: c_int,
fragment_len: u64,
destination_idx: c_int,
out_fragment: *mut u8,
) -> Desc;
}
pub fn instance_create(id: EcBackendId, args: &EcArgs) -> Result<Desc, ErrorCode> {
match unsafe { liberasurecode_instance_create(id, args) } {
desc if desc > 0 => Ok(desc),
code => Err(-code as ErrorCode),
}
}
pub fn instance_destroy(desc: Desc) -> Result<(), ErrorCode> {
match unsafe { liberasurecode_instance_destroy(desc) } {
0 => Ok(()),
code => Err(code as ErrorCode),
}
}
pub fn encode(
desc: Desc,
orig_data: &[u8],
) -> Result<(*mut *mut u8, *mut *mut u8, u64), ErrorCode> {
let mut encoded_data = ptr::null_mut();
let mut encoded_parity = ptr::null_mut();
let mut fragment_len = 0;
let result = unsafe {
liberasurecode_encode(
desc,
orig_data.as_ptr(),
orig_data.len() as u64,
&mut encoded_data,
&mut encoded_parity,
&mut fragment_len,
)
};
match result {
0 => Ok((encoded_data, encoded_parity, fragment_len)),
_ => Err(-result as ErrorCode),
}
}
pub fn encode_cleanup(
desc: Desc,
encoded_data: *mut *mut u8,
encoded_parity: *mut *mut u8,
) -> Result<(), ErrorCode> {
match unsafe { liberasurecode_encode_cleanup(desc, encoded_data, encoded_parity) } {
0 => Ok(()),
code => Err(-code as ErrorCode),
}
}
pub fn decode(
desc: Desc,
fragments: &[&[u8]],
force_metadata_checks: bool,
) -> Result<(*mut u8, u64), ErrorCode> {
assert!(!fragments.is_empty());
let mut out_data = ptr::null_mut();
let mut out_data_len = 0;
let result = unsafe {
liberasurecode_decode(
desc,
fragments
.iter()
.map(|x| x.as_ptr())
.collect::<Vec<_>>()
.as_ptr(),
fragments.len() as c_int,
fragments[0].len() as u64,
if force_metadata_checks { 1 } else { 0 },
&mut out_data,
&mut out_data_len,
)
};
match result {
0 => Ok((out_data, out_data_len)),
_ => Err(-result as ErrorCode),
}
}
pub fn decode_cleanup(desc: Desc, data: *mut u8) -> Result<(), ErrorCode> {
match unsafe { liberasurecode_decode_cleanup(desc, data) } {
0 => Ok(()),
code => Err(-code as ErrorCode),
}
}
pub fn reconstruct_fragment(
desc: Desc,
available_fragments: &[&[u8]],
destination_idx: usize,
) -> Result<Vec<u8>, ErrorCode> {
assert!(!available_fragments.is_empty());
let mut buf = vec![0; available_fragments[0].len()];
let result = unsafe {
liberasurecode_reconstruct_fragment(
desc,
available_fragments
.iter()
.map(|x| x.as_ptr())
.collect::<Vec<_>>()
.as_ptr(),
available_fragments.len() as c_int,
available_fragments[0].len() as u64,
destination_idx as c_int,
buf.as_mut_ptr(),
)
};
match result {
0 => Ok(buf),
_ => Err(-result as ErrorCode),
}
}