use std::panic::{AssertUnwindSafe, catch_unwind};
use crate::lepton_error::{ExitCode, LeptonError};
pub fn catch_unwind_result<R>(
f: impl FnOnce() -> Result<R, LeptonError>,
) -> Result<R, LeptonError> {
match catch_unwind(AssertUnwindSafe(f)) {
Ok(r) => r.map_err(|e| e.into()),
Err(err) => {
if let Some(message) = err.downcast_ref::<&str>() {
Err(LeptonError::new(ExitCode::AssertionFailure, *message))
} else if let Some(message) = err.downcast_ref::<String>() {
Err(LeptonError::new(ExitCode::AssertionFailure, message))
} else {
Err(LeptonError::new(
ExitCode::AssertionFailure,
"unknown panic",
))
}
}
}
}
#[inline(always)]
pub const fn u16_bit_length(v: u16) -> u8 {
return 16 - v.leading_zeros() as u8;
}
#[inline(always)]
pub const fn u32_bit_length(v: u32) -> u8 {
return 32 - v.leading_zeros() as u8;
}
pub fn buffer_prefix_matches_marker<const BS: usize, const MS: usize>(
buffer: [u8; BS],
marker: [u8; MS],
) -> bool {
for i in 0..marker.len() {
if buffer[i] != marker[i] {
return false;
}
}
return true;
}
#[inline(always)]
pub fn has_ff(v: u64) -> bool {
(v & 0x8080808080808080 & !v.wrapping_add(0x0101010101010101)) != 0
}
#[inline(always)]
pub const fn devli(s: u8, value: u16) -> i16 {
let shifted = 1 << s;
if value & (shifted >> 1) != 0 {
value as i16
} else {
value.wrapping_add(2).wrapping_add(!shifted) as i16
}
}
#[test]
fn devli_test() {
for s in 0u8..15 {
for value in 0..(1 << s) {
assert_eq!(
devli(s, value),
if s == 0 {
value as i16
} else if value < (1 << (s as u16 - 1)) {
value as i16 + (-1 << s as i16) + 1
} else {
value as i16
}
);
}
}
}
#[inline(always)]
pub const fn b_short(v1: u8, v2: u8) -> u16 {
((v1 as u16) << 8) + v2 as u16
}
#[inline(always)]
pub const fn rbits(c: u8, n: usize) -> u8 {
return c & (0xFF >> (8 - n));
}
#[inline(always)]
pub const fn lbits(c: u8, n: usize) -> u8 {
return c >> (8 - n);
}
#[inline(always)]
pub const fn bitn(c: u16, n: u16) -> u8 {
return ((c >> n) & 0x1) as u8;
}
#[inline(always)]
pub fn calc_sign_index(val: i16) -> usize {
if val == 0 {
0
} else {
if val > 0 { 1 } else { 2 }
}
}
#[inline(always)]
pub fn needs_to_grow<T>(v: &Vec<T>, additional: usize) -> bool {
additional > v.capacity().wrapping_sub(v.len())
}
#[cfg(test)]
pub fn get_rand_from_seed(seed: [u8; 32]) -> rand_chacha::ChaCha12Rng {
use rand_chacha::ChaCha12Rng;
use rand_chacha::rand_core::SeedableRng;
ChaCha12Rng::from_seed(seed)
}
#[cfg(any(test, feature = "micro_benchmark"))]
pub fn read_file(filename: &str, ext: &str) -> Vec<u8> {
use std::io::Read;
let filename = std::path::Path::new(env!("WORKSPACE_ROOT"))
.join("images")
.join(filename.to_owned() + ext);
let mut f = std::fs::File::open(filename).unwrap();
let mut content = Vec::new();
f.read_to_end(&mut content).unwrap();
content
}