use bytes::Bytes;
use smol_str::SmolStr;
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::composite::cover_art")
)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CoverArt {
mime: SmolStr,
data: Bytes,
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
const _: () = {
use serde::{Deserialize, Deserializer, Serialize, Serializer, ser::SerializeStruct};
impl Serialize for CoverArt {
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
let mut st = ser.serialize_struct("CoverArt", 2)?;
st.serialize_field("mime", &self.mime)?;
st.serialize_field("data", &self.data)?;
st.end()
}
}
#[derive(Deserialize)]
struct Shadow {
mime: SmolStr,
data: Bytes,
}
impl<'de> Deserialize<'de> for CoverArt {
fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
let s = Shadow::deserialize(de)?;
CoverArt::try_new(s.mime, s.data).map_err(serde::de::Error::custom)
}
}
};
impl Default for CoverArt {
fn default() -> Self {
Self {
mime: SmolStr::new_static("application/octet-stream"),
data: Bytes::from_static(&[0u8]),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, thiserror::Error)]
#[non_exhaustive]
pub enum CoverArtError {
#[error("audio cover-art mime type is empty")]
EmptyMime,
#[error("audio cover-art data is empty")]
EmptyData,
}
impl CoverArt {
pub fn try_new(mime: impl Into<SmolStr>, data: impl Into<Bytes>) -> Result<Self, CoverArtError> {
let mime = mime.into();
if mime.is_empty() {
return Err(CoverArtError::EmptyMime);
}
let data = data.into();
if data.is_empty() {
return Err(CoverArtError::EmptyData);
}
Ok(Self { mime, data })
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn mime(&self) -> &str {
self.mime.as_str()
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn data(&self) -> &[u8] {
self.data.as_ref()
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn data_bytes(&self) -> Bytes {
self.data.clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
use ::std::vec;
#[test]
fn try_new_happy_path() {
let art = CoverArt::try_new("image/jpeg", vec![0xFFu8, 0xD8, 0xFF]).unwrap();
assert_eq!(art.mime(), "image/jpeg");
assert_eq!(art.data(), &[0xFF, 0xD8, 0xFF]);
}
#[test]
fn try_new_rejects_empty_mime() {
let err = CoverArt::try_new("", vec![1u8, 2, 3]).unwrap_err();
assert_eq!(err, CoverArtError::EmptyMime);
}
#[test]
fn try_new_rejects_empty_data() {
let err = CoverArt::try_new("image/png", vec![]).unwrap_err();
assert_eq!(err, CoverArtError::EmptyData);
}
}