screencapturekit/utils/
four_char_code.rs

1//! Minimal `FourCharCode` implementation for pixel formats and color conversions
2//!
3//! A `FourCharCode` is a 4-byte code used in Core Video and Core Media to identify
4//! pixel formats, codecs, and other media types.
5
6use std::fmt;
7use std::str::FromStr;
8
9/// `FourCharCode` represents a 4-character code (used in Core Video/Media)
10///
11/// # Examples
12///
13/// ```
14/// use screencapturekit::FourCharCode;
15///
16/// // Create from string
17/// let code: FourCharCode = "BGRA".parse().unwrap();
18/// assert_eq!(code.display(), "BGRA");
19///
20/// // Create from bytes
21/// let code = FourCharCode::from_bytes(*b"420v");
22/// assert_eq!(code.as_u32(), 0x34323076);
23/// ```
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
25pub struct FourCharCode(u32);
26
27impl FourCharCode {
28    /// Create a `FourCharCode` from exactly 4 bytes (infallible)
29    ///
30    /// # Examples
31    ///
32    /// ```
33    /// use screencapturekit::FourCharCode;
34    ///
35    /// let code = FourCharCode::from_bytes(*b"BGRA");
36    /// assert_eq!(code.display(), "BGRA");
37    /// ```
38    #[inline]
39    pub const fn from_bytes(bytes: [u8; 4]) -> Self {
40        Self(u32::from_be_bytes(bytes))
41    }
42
43    /// Create a `FourCharCode` from a byte slice
44    pub fn from_slice(bytes: &[u8]) -> Option<Self> {
45        if bytes.len() != 4 {
46            return None;
47        }
48
49        let code = u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
50        Some(Self(code))
51    }
52
53    /// Get the u32 representation
54    ///
55    /// # Examples
56    ///
57    /// ```
58    /// use screencapturekit::FourCharCode;
59    ///
60    /// let code = FourCharCode::from_bytes(*b"BGRA");
61    /// let value: u32 = code.as_u32();
62    /// assert_eq!(value, 0x42475241);
63    /// ```
64    #[inline]
65    pub const fn as_u32(self) -> u32 {
66        self.0
67    }
68
69    /// Get the bytes as an array
70    #[inline]
71    pub const fn as_bytes(self) -> [u8; 4] {
72        self.0.to_be_bytes()
73    }
74
75    /// Create from a u32 value (const version of From trait)
76    #[inline]
77    pub const fn from_u32(value: u32) -> Self {
78        Self(value)
79    }
80
81    /// Compare with another `FourCharCode` at compile time
82    #[inline]
83    pub const fn equals(self, other: Self) -> bool {
84        self.0 == other.0
85    }
86
87    /// Display the code as a string
88    pub fn display(self) -> String {
89        let bytes = self.0.to_be_bytes();
90        String::from_utf8_lossy(&bytes).to_string()
91    }
92}
93
94impl FromStr for FourCharCode {
95    type Err = &'static str;
96
97    fn from_str(s: &str) -> Result<Self, Self::Err> {
98        if s.len() != 4 {
99            return Err("FourCharCode must be exactly 4 characters");
100        }
101        if !s.is_ascii() {
102            return Err("FourCharCode must contain only ASCII characters");
103        }
104
105        let bytes = s.as_bytes();
106        let code = u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
107        Ok(Self(code))
108    }
109}
110
111impl From<u32> for FourCharCode {
112    fn from(value: u32) -> Self {
113        Self(value)
114    }
115}
116
117impl From<FourCharCode> for u32 {
118    fn from(code: FourCharCode) -> Self {
119        code.0
120    }
121}
122
123impl fmt::Display for FourCharCode {
124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125        write!(f, "{}", self.display())
126    }
127}