use derive_more::Deref;
use std::fmt;
#[derive(Default, Clone, Copy, Deref, PartialEq, Eq)]
pub struct FourCC(pub(crate) [u8; 4]);
impl FourCC {
pub const fn new(typ: &[u8; 4]) -> Self {
Self(*typ)
}
pub fn into_bytes(self) -> [u8; 4] {
self.0
}
pub fn as_bytes(&self) -> &[u8; 4] {
&self.0
}
pub fn as_str(&self) -> &str {
std::str::from_utf8(&self.0).unwrap_or("????")
}
}
impl From<[u8; 4]> for FourCC {
fn from(value: [u8; 4]) -> Self {
FourCC(value)
}
}
impl PartialEq<&[u8; 4]> for FourCC {
fn eq(&self, other: &&[u8; 4]) -> bool {
&self.0 == *other
}
}
impl PartialEq<[u8; 4]> for FourCC {
fn eq(&self, other: &[u8; 4]) -> bool {
&self.0 == other
}
}
impl fmt::Display for FourCC {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let fourcc = std::str::from_utf8(&self.0)
.map_or_else(|_| convert_mac_roman_to_utf8(&self.0), ToOwned::to_owned);
if fourcc
.trim_matches(|c| !char::is_ascii_alphanumeric(&c))
.is_empty()
{
fmt::Debug::fmt(&self.0, f)
} else {
write!(f, "{fourcc}")
}
}
}
impl fmt::Debug for FourCC {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "FourCC({self})")
}
}
fn convert_mac_roman_to_utf8(bytes: &[u8]) -> String {
let mut result = String::new();
for &byte in bytes {
match byte {
0xA9 => result.push('©'), 0xAE => result.push('®'), 0x99 => result.push('™'), b if b.is_ascii() => result.push(b as char),
_ => result.push('�'),
}
}
result
}