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}