use bytes::Bytes;
use smol_str::SmolStr;
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::composite::fingerprint")
)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Fingerprint {
algorithm: SmolStr,
value: Bytes,
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
const _: () = {
use serde::{Deserialize, Deserializer, Serialize, Serializer, ser::SerializeStruct};
impl Serialize for Fingerprint {
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
let mut st = ser.serialize_struct("Fingerprint", 2)?;
st.serialize_field("algorithm", &self.algorithm)?;
st.serialize_field("value", &self.value)?;
st.end()
}
}
#[derive(Deserialize)]
struct Shadow {
algorithm: SmolStr,
value: Bytes,
}
impl<'de> Deserialize<'de> for Fingerprint {
fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
let s = Shadow::deserialize(de)?;
Fingerprint::try_new(s.algorithm, s.value).map_err(serde::de::Error::custom)
}
}
};
impl Default for Fingerprint {
fn default() -> Self {
Self {
algorithm: SmolStr::new_inline("default"),
value: Bytes::new(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, thiserror::Error)]
#[non_exhaustive]
pub enum FingerprintError {
#[error("audio fingerprint algorithm label is empty")]
EmptyAlgorithm,
}
impl Fingerprint {
pub fn try_new(
algorithm: impl Into<SmolStr>,
value: impl Into<Bytes>,
) -> Result<Self, FingerprintError> {
let algorithm = algorithm.into();
if algorithm.is_empty() {
return Err(FingerprintError::EmptyAlgorithm);
}
Ok(Self {
algorithm,
value: value.into(),
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn algorithm(&self) -> &str {
self.algorithm.as_str()
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn value(&self) -> &[u8] {
self.value.as_ref()
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn value_bytes(&self) -> Bytes {
self.value.clone()
}
}
#[cfg(test)]
mod tests;