#![deny(clippy::unwrap_used)]
#![forbid(
clippy::exit,
clippy::mem_forget,
clippy::large_include_file,
clippy::fn_to_numeric_cast_any,
clippy::cast_precision_loss,
clippy::float_arithmetic,
clippy::excessive_precision,
clippy::lossy_float_literal,
clippy::float_cmp,
clippy::float_cmp_const
)]
pub const DEFAULT_LEN: usize = 8;
#[allow(clippy::inline_always)]
#[inline(always)]
const fn div_ceil(n: usize, d: usize) -> usize {
n / d + (if n % d == 0 { 0 } else { 1 })
}
#[inline]
const fn next_multiple(n: usize, d: usize) -> usize {
match d {
0 => d,
_ => div_ceil(n, d) * d,
}
}
pub fn u8vec_to_hex_outplace(v: &Vec<u8>) -> String {
use std::fmt::Write as _;
let mut hex = String::with_capacity(v.len() * 2);
for byte in v {
let _ = write!(hex, "{:02x}", byte);
}
hex
}
pub fn u8vec_to_hex_inplace(mut v: Vec<u8>) -> String {
const TABLE: &[u8; 0x10] = b"0123456789abcdef";
let len = v.len();
v.resize(len * 2, 0);
if len > 0 {
let mut i = len;
loop {
i -= 1;
v[i * 2 + 1] = TABLE[(v[i] & 0xf) as usize];
v[i * 2] = TABLE[(v[i] >> 4) as usize];
if i == 0 {
break;
}
}
}
#[allow(clippy::unwrap_used)]
String::from_utf8(v).unwrap()
}
fn xor_hasher(bytes: &[u8], mut sbox: Vec<u8>) -> Vec<u8> {
let len = sbox.len();
if len > 0 {
for chunk in bytes.chunks(len) {
chunk.iter().zip(&mut sbox).for_each(|(&b, k)| *k ^= b);
}
}
sbox
}
#[cfg(test)]
#[test]
fn test_hasher() {
assert_eq!(xor_hasher(&[0], vec![0; DEFAULT_LEN]), vec![0; DEFAULT_LEN]);
}
pub fn stream_processor(
stream: impl std::io::Read,
mut sbox: Vec<u8>,
) -> std::io::Result<Vec<u8>> {
let len = sbox.len();
if len > 0 {
let buf_len = {
const DEFAULT_BUF_LEN: usize = 0x10000;
if DEFAULT_BUF_LEN > len {
next_multiple(DEFAULT_BUF_LEN, len)
} else {
len
}
};
let mut reader = std::io::BufReader::with_capacity(buf_len, stream);
loop {
use std::io::BufRead as _;
let read_buf = reader.fill_buf()?;
let read_len = read_buf.len();
if read_len == 0 {
break;
}
sbox = xor_hasher(read_buf, sbox);
reader.consume(read_len);
}
}
Ok(sbox)
}
#[cfg(test)]
mod tests {
#[allow(clippy::wildcard_imports)]
use crate::module::*;
#[test]
#[allow(clippy::cast_possible_truncation)] fn hex_cmp() {
const L: usize = 0x100;
let mut v: Vec<u8> = vec![0; L];
for (i, b) in v.iter_mut().enumerate() {
*b = i as u8;
}
assert_eq!(u8vec_to_hex_inplace(v.clone()), u8vec_to_hex_outplace(&v));
}
}