use std::hash::{Hash, Hasher as StdHasher};
#[cfg(feature = "digest")]
use digest::{Digest as TraitDigest, Update as TraitUpdate};
#[cfg(feature = "digest_mac")]
use digest::Mac as TraitMac;
use crate::phonenumber_mask::helper_types;
use crate::{PhoneNumber as LocalPhoneNumber, interfaces::PhoneHasher as TraitPhoneHasher};
use crate::{interfaces::OptionalHasher, phonenumber_mask::Hashed as LocalHashed};
#[repr(transparent)]
pub struct PhoneStdHasher<T: StdHasher>(pub T);
#[cfg(feature = "digest")]
#[repr(transparent)]
pub struct PhoneDigestHasher<T: TraitDigest + TraitUpdate>(pub T);
#[cfg(feature = "digest_mac")]
#[repr(transparent)]
pub struct PhoneMacHasher<T: TraitMac + TraitUpdate>(pub T);
impl<T: StdHasher> TraitPhoneHasher for PhoneStdHasher<T> {
fn hash_phone(mut self, phone: &LocalPhoneNumber) -> helper_types::Result<LocalHashed> {
phone.hash(&mut self.0);
LocalHashed::from_slice(self.0.finish().to_be_bytes())
}
}
#[cfg(feature = "digest")]
impl<T: TraitDigest + TraitUpdate> PhoneDigestHasher<T> {
pub fn new_with_salt(mut digest: T, salt: &[u8]) -> Self {
TraitUpdate::update(&mut digest, salt);
Self(digest)
}
}
#[cfg(feature = "digest")]
fn feed_phone_bytes(updater: &mut impl TraitUpdate, phone: &LocalPhoneNumber) {
updater.update(&phone.country_code.to_be_bytes());
updater.update(&phone.national_number.to_be_bytes());
updater.update(&phone.extension().len().to_be_bytes());
updater.update(phone.extension().as_bytes());
updater.update(&[phone.italian_leading_zero() as u8]);
updater.update(&phone.number_of_leading_zeros().to_be_bytes());
updater.update(&phone.raw_input().len().to_be_bytes());
updater.update(phone.raw_input().as_bytes());
updater.update(&(phone.country_code_source() as i32).to_be_bytes());
updater.update(phone.preferred_domestic_carrier_code().as_bytes());
}
#[cfg(feature = "digest")]
impl<D: TraitDigest + TraitUpdate> TraitPhoneHasher for PhoneDigestHasher<D> {
fn hash_phone(mut self, phone: &LocalPhoneNumber) -> helper_types::Result<LocalHashed> {
feed_phone_bytes(&mut self.0, phone);
let out = self.0.finalize();
LocalHashed::from_slice(out)
}
}
#[cfg(feature = "digest_mac")]
impl<M: TraitMac + TraitUpdate> TraitPhoneHasher for PhoneMacHasher<M> {
fn hash_phone(mut self, phone: &LocalPhoneNumber) -> helper_types::Result<LocalHashed> {
feed_phone_bytes(&mut self.0, phone);
let out = self.0.finalize();
LocalHashed::from_slice(out.as_bytes())
}
}
impl OptionalHasher for () {
fn hash_phone(self, _: &LocalPhoneNumber) -> helper_types::Result<Option<LocalHashed>> {
Ok(None)
}
}