use std::fmt;
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FourCharCode(u32);
impl FourCharCode {
#[inline]
pub const fn from_bytes(bytes: [u8; 4]) -> Self {
Self(u32::from_be_bytes(bytes))
}
pub fn from_slice(bytes: &[u8]) -> Option<Self> {
if bytes.len() != 4 {
return None;
}
let code = u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
Some(Self(code))
}
#[inline]
pub const fn as_u32(self) -> u32 {
self.0
}
#[inline]
pub const fn as_bytes(self) -> [u8; 4] {
self.0.to_be_bytes()
}
#[inline]
pub const fn from_u32(value: u32) -> Self {
Self(value)
}
#[inline]
pub const fn equals(self, other: Self) -> bool {
self.0 == other.0
}
pub fn display(self) -> String {
let bytes = self.0.to_be_bytes();
String::from_utf8_lossy(&bytes).to_string()
}
}
impl FromStr for FourCharCode {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.len() != 4 {
return Err("FourCharCode must be exactly 4 characters");
}
if !s.is_ascii() {
return Err("FourCharCode must contain only ASCII characters");
}
let bytes = s.as_bytes();
let code = u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
Ok(Self(code))
}
}
impl From<u32> for FourCharCode {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<FourCharCode> for u32 {
fn from(code: FourCharCode) -> Self {
code.0
}
}
impl fmt::Display for FourCharCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display())
}
}