use crate::compare::dist_qratios::{distance, MAX_DISTANCE};
use crate::errors::ParseError;
use crate::parse::hex_str::decode_rev_1;
#[bitfield_struct::bitfield(u8, order = Lsb)]
#[derive(PartialEq, Eq)]
struct InnerQRatios {
#[bits(4)]
q1ratio: u8,
#[bits(4)]
q2ratio: u8,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct FuzzyHashQRatios {
qratios: InnerQRatios,
}
impl FuzzyHashQRatios {
pub const MAX_DISTANCE: u32 = MAX_DISTANCE;
#[inline(always)]
pub(crate) fn new(q1ratio: u8, q2ratio: u8) -> Self {
Self {
qratios: InnerQRatios::new()
.with_q1ratio(q1ratio)
.with_q2ratio(q2ratio),
}
}
#[inline(always)]
pub(crate) fn from_raw(qratios: u8) -> Self {
Self {
qratios: InnerQRatios::from(qratios),
}
}
#[inline]
pub(crate) fn from_str_bytes(bytes: &[u8]) -> Result<Self, ParseError> {
if bytes.len() != 2 {
return Err(ParseError::InvalidStringLength);
}
decode_rev_1(bytes)
.ok_or(ParseError::InvalidCharacter)
.map(Self::from_raw)
}
#[inline(always)]
pub fn value(&self) -> u8 {
self.qratios.into_bits()
}
#[inline(always)]
pub fn q1ratio(&self) -> u8 {
self.qratios.q1ratio()
}
#[inline(always)]
pub fn q2ratio(&self) -> u8 {
self.qratios.q2ratio()
}
#[inline(always)]
pub fn compare(&self, other: &FuzzyHashQRatios) -> u32 {
distance(self.qratios.into_bits(), other.qratios.into_bits())
}
}
mod tests;