mp4_atom/
types.rs

1use std::fmt;
2
3use crate::*;
4
5// Re-export this common types.
6pub use num::rational::Ratio;
7
8/// A four-character code used to identify atoms.
9#[derive(Clone, Copy, PartialEq, Eq)]
10// TODO serialize as a string
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub struct FourCC([u8; 4]);
13
14impl FourCC {
15    // Helper function to create a FourCC from a string literal
16    // ex. FourCC::new(b"abcd")
17    pub const fn new(value: &[u8; 4]) -> Self {
18        FourCC(*value)
19    }
20}
21
22impl From<u32> for FourCC {
23    fn from(value: u32) -> Self {
24        FourCC(value.to_be_bytes())
25    }
26}
27
28impl From<FourCC> for u32 {
29    fn from(cc: FourCC) -> Self {
30        u32::from_be_bytes(cc.0)
31    }
32}
33
34impl From<[u8; 4]> for FourCC {
35    fn from(value: [u8; 4]) -> Self {
36        FourCC(value)
37    }
38}
39
40impl From<FourCC> for [u8; 4] {
41    fn from(cc: FourCC) -> Self {
42        cc.0
43    }
44}
45
46impl From<&[u8; 4]> for FourCC {
47    fn from(value: &[u8; 4]) -> Self {
48        FourCC(*value)
49    }
50}
51
52impl fmt::Display for FourCC {
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54        let s = String::from_utf8_lossy(&self.0);
55        write!(f, "{}", s)
56    }
57}
58
59impl fmt::Debug for FourCC {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        let s = String::from_utf8_lossy(&self.0);
62        write!(f, "{}", s)
63    }
64}
65
66impl Encode for FourCC {
67    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
68        self.0.encode(buf)
69    }
70}
71
72impl Decode for FourCC {
73    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
74        Ok(FourCC(<[u8; 4]>::decode(buf)?))
75    }
76}
77
78impl AsRef<[u8; 4]> for FourCC {
79    fn as_ref(&self) -> &[u8; 4] {
80        &self.0
81    }
82}
83
84#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
85#[allow(non_camel_case_types)]
86#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
87pub struct u24([u8; 3]);
88
89impl Decode for u24 {
90    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
91        Ok(Self(<[u8; 3]>::decode(buf)?))
92    }
93}
94
95impl Encode for u24 {
96    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
97        self.0.encode(buf)
98    }
99}
100
101impl From<u24> for u32 {
102    fn from(value: u24) -> Self {
103        u32::from_be_bytes([0, value.0[0], value.0[1], value.0[2]])
104    }
105}
106
107impl TryFrom<u32> for u24 {
108    type Error = std::array::TryFromSliceError;
109
110    fn try_from(value: u32) -> std::result::Result<Self, Self::Error> {
111        Ok(Self(value.to_be_bytes()[1..].try_into()?))
112    }
113}
114
115#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
116#[allow(non_camel_case_types)]
117#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
118pub struct u48([u8; 6]);
119
120impl Decode for u48 {
121    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
122        Ok(Self(<[u8; 6]>::decode(buf)?))
123    }
124}
125
126impl Encode for u48 {
127    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
128        self.0.encode(buf)
129    }
130}
131
132impl TryFrom<u64> for u48 {
133    type Error = std::array::TryFromSliceError;
134
135    fn try_from(value: u64) -> std::result::Result<Self, Self::Error> {
136        Ok(Self(value.to_be_bytes()[2..].try_into()?))
137    }
138}
139
140impl From<u48> for u64 {
141    fn from(value: u48) -> Self {
142        u64::from_be_bytes([
143            0, 0, value.0[0], value.0[1], value.0[2], value.0[3], value.0[4], value.0[5],
144        ])
145    }
146}
147
148// The top N bits are the integer part, the bottom N bits are the fractional part.
149// Somebody who cares should implement some math stuff.
150#[derive(Copy, Clone, Default, PartialEq, Eq)]
151#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
152pub struct FixedPoint<T> {
153    int: T,
154    dec: T,
155}
156
157impl<T: Copy> FixedPoint<T> {
158    pub fn new(int: T, dec: T) -> Self {
159        Self { int, dec }
160    }
161
162    pub fn integer(&self) -> T {
163        self.int
164    }
165
166    pub fn decimal(&self) -> T {
167        self.dec
168    }
169}
170
171impl<T: Decode> Decode for FixedPoint<T> {
172    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
173        Ok(Self {
174            int: T::decode(buf)?,
175            dec: T::decode(buf)?,
176        })
177    }
178}
179
180impl<T: Encode> Encode for FixedPoint<T> {
181    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
182        self.int.encode(buf)?;
183        self.dec.encode(buf)
184    }
185}
186
187impl<T: num::Zero> From<T> for FixedPoint<T> {
188    fn from(value: T) -> Self {
189        Self {
190            int: value,
191            dec: T::zero(),
192        }
193    }
194}
195
196impl<T> fmt::Debug for FixedPoint<T>
197where
198    T: num::Zero + fmt::Debug + PartialEq + Copy,
199    f64: From<T>,
200{
201    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
202        if self.dec.is_zero() {
203            write!(f, "{:?}", self.int)
204        } else {
205            write!(f, "{:?}", f64::from(self.int) / f64::from(self.dec))
206        }
207    }
208}
209
210// 32 bytes max
211#[derive(Debug, Clone, PartialEq, Eq, Default)]
212#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
213pub struct Compressor(String);
214
215impl From<&str> for Compressor {
216    fn from(value: &str) -> Self {
217        Self(value.to_string())
218    }
219}
220
221impl From<String> for Compressor {
222    fn from(value: String) -> Self {
223        Self(value)
224    }
225}
226
227impl From<Compressor> for String {
228    fn from(value: Compressor) -> Self {
229        value.0
230    }
231}
232
233impl AsRef<str> for Compressor {
234    fn as_ref(&self) -> &str {
235        &self.0
236    }
237}
238
239impl Encode for Compressor {
240    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
241        let name = self.0.as_bytes();
242        let max = name.len().min(31);
243        (&name[..max]).encode(buf)?;
244
245        let zero = [0u8; 32];
246        (&zero[..32 - max]).encode(buf)
247    }
248}
249
250impl Decode for Compressor {
251    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
252        let name = <[u8; 32]>::decode(buf)?;
253
254        let name = String::from_utf8_lossy(&name)
255            .trim_end_matches('\0')
256            .to_string();
257
258        Ok(Self(name))
259    }
260}
261
262#[derive(Debug, Clone, PartialEq, Eq, Default)]
263pub struct Zeroed {
264    pub size: usize,
265}
266
267impl Zeroed {
268    pub fn new(size: usize) -> Self {
269        Self { size }
270    }
271}
272
273impl Encode for Zeroed {
274    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
275        let zero = [0u8; 32];
276        let mut size = self.size;
277
278        while size > 0 {
279            let len = zero.len().min(size);
280            (&zero[..len]).encode(buf)?;
281            size -= len;
282        }
283
284        Ok(())
285    }
286}
287
288impl Decode for Zeroed {
289    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
290        let size = buf.remaining();
291        buf.advance(size);
292        Ok(Self { size })
293    }
294}
295
296impl From<usize> for Zeroed {
297    fn from(size: usize) -> Self {
298        Self { size }
299    }
300}