use std::fmt::Display;
use ltk_hash::{HashAlgorithm, HashValue, HashWidth, Hasher};
use ltk_meta::PropertyKind;
use crate::RitobinName as _;
pub const fn hash_algorithm_name(algorithm: HashAlgorithm) -> &'static str {
match algorithm {
HashAlgorithm::Fnv1a32 => "fnv1a",
HashAlgorithm::Xxh64 => "xxh64",
HashAlgorithm::Xxh3 => "xxh3",
_ => "unknown",
}
}
pub fn hash_algorithm_from_name(name: &str) -> Option<HashAlgorithm> {
match name {
"fnv1a" => Some(HashAlgorithm::Fnv1a32),
"xxh64" => Some(HashAlgorithm::Xxh64),
"xxh3" => Some(HashAlgorithm::Xxh3),
_ => None,
}
}
pub const fn hash_width_name(width: HashWidth) -> &'static str {
match width {
HashWidth::W4 => "u32",
HashWidth::W8 => "u64",
}
}
pub fn hash_width_from_name(name: &str) -> Option<HashWidth> {
match name {
"u32" => Some(HashWidth::W4),
"u64" => Some(HashWidth::W8),
_ => None,
}
}
pub const fn rito_hasher(width: HashWidth, algorithm: HashAlgorithm) -> Hasher {
Hasher {
width,
algorithm,
lowercased: true,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, std::hash::Hash)]
pub struct HashType {
pub width: HashWidth,
pub algorithm: Option<HashAlgorithm>,
}
impl HashType {
pub const DEFAULT: Self = Self::new(HashWidth::W4, HashAlgorithm::Fnv1a32);
pub const fn new(width: HashWidth, algorithm: HashAlgorithm) -> Self {
Self {
width,
algorithm: Some(algorithm),
}
}
pub const fn width_only(width: HashWidth) -> Self {
Self {
width,
algorithm: None,
}
}
pub const fn hasher(self) -> Option<Hasher> {
match self.algorithm {
Some(algorithm) => Some(rito_hasher(self.width, algorithm)),
None => None,
}
}
pub const fn from_hash(self, hash: u64) -> HashValue {
HashValue::with_width(hash, self.width)
}
pub fn hash_str(self, text: &str) -> Option<HashValue> {
Some(self.hasher()?.hash_str(text))
}
}
impl Default for HashType {
fn default() -> Self {
Self::DEFAULT
}
}
impl Display for HashType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(PropertyKind::Hash.to_rito_name())?;
if *self == Self::DEFAULT {
return Ok(());
}
write!(f, "[{}", hash_width_name(self.width))?;
if let Some(algorithm) = self.algorithm {
write!(f, ",{}", hash_algorithm_name(algorithm))?;
}
f.write_str("]")
}
}
pub const fn hash_type_for_width(width: HashWidth) -> HashType {
match width {
HashWidth::W4 => HashType::DEFAULT,
HashWidth::W8 => HashType::width_only(HashWidth::W8),
}
}