use std::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
#[cfg(feature = "args")]
use clap::{Parser, ValueEnum};
#[cfg(feature = "args")]
#[derive(Debug, ValueEnum, Clone)]
pub enum HashingAlgo {
Sha512,
Sha256,
MD5,
}
#[cfg(feature = "args")]
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
pub struct Args {
#[arg(short, long, value_enum)]
pub algo: HashingAlgo,
#[arg(short, long)]
pub file: Option<String>,
#[arg(short, long)]
pub time: bool,
}
pub(crate) fn big_sigma<T>(x: T, (a, b, c): (usize, usize, usize)) -> T
where
T: Shr<usize, Output = T>
+ Shl<usize, Output = T>
+ BitOr<T, Output = T>
+ BitXor<T, Output = T>
+ Clone
+ Copy,
{
right_rotate(x, a) ^ right_rotate(x, b) ^ right_rotate(x, c)
}
pub(crate) fn small_sigma<T>(x: T, (a, b, c): (usize, usize, usize)) -> T
where
T: Shr<usize, Output = T>
+ Shl<usize, Output = T>
+ BitOr<T, Output = T>
+ BitXor<T, Output = T>
+ Clone
+ Copy,
{
right_rotate(x, a) ^ right_rotate(x, b) ^ right_shift(x, c)
}
pub(crate) fn left_rotate<T>(num: T, bits: usize) -> T
where
T: Shr<usize, Output = T> + Shl<usize, Output = T> + BitOr<T, Output = T> + Clone,
{
let bit_width = std::mem::size_of_val(&num) * 8;
let bits = bits % bit_width;
(num.clone() << bits) | (num >> (bit_width - bits))
}
pub(crate) fn right_rotate<T>(num: T, bits: usize) -> T
where
T: Shr<usize, Output = T> + Shl<usize, Output = T> + BitOr<T, Output = T> + Clone,
{
let bit_width = std::mem::size_of_val(&num) * 8;
let bits = bits % bit_width;
(num.clone() << (bit_width - bits)) | (num >> bits)
}
pub(crate) fn right_shift<T>(num: T, bits: usize) -> T
where
T: Shr<usize, Output = T>,
{
let bits = bits % (std::mem::size_of::<T>() * 8);
num >> bits
}
pub(crate) fn ch<T>(x: T, y: T, z: T) -> T
where
T: BitAnd<T, Output = T> + BitXor<T, Output = T> + Not<Output = T> + Copy,
{
(x & y) ^ (!x & z)
}
pub(crate) fn maj<T>(x: T, y: T, z: T) -> T
where
T: BitAnd<T, Output = T> + BitXor<T, Output = T> + Copy,
{
(x & y) ^ (x & z) ^ (y & z)
}