Skip to main content

mp4_atom/
types.rs

1use std::fmt;
2
3use crate::*;
4
5// Re-export this common types.
6pub use num::rational::Ratio;
7pub use num::traits::ToBytes;
8
9/// A four-character code used to identify atoms.
10#[derive(Clone, Copy, PartialEq, Eq, Hash)]
11// TODO serialize as a string
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct FourCC([u8; 4]);
14
15impl FourCC {
16    // Helper function to create a FourCC from a string literal
17    // ex. FourCC::new(b"abcd")
18    pub const fn new(value: &[u8; 4]) -> Self {
19        FourCC(*value)
20    }
21}
22
23impl From<u32> for FourCC {
24    fn from(value: u32) -> Self {
25        FourCC(value.to_be_bytes())
26    }
27}
28
29impl From<FourCC> for u32 {
30    fn from(cc: FourCC) -> Self {
31        u32::from_be_bytes(cc.0)
32    }
33}
34
35impl From<[u8; 4]> for FourCC {
36    fn from(value: [u8; 4]) -> Self {
37        FourCC(value)
38    }
39}
40
41impl From<FourCC> for [u8; 4] {
42    fn from(cc: FourCC) -> Self {
43        cc.0
44    }
45}
46
47impl From<&[u8; 4]> for FourCC {
48    fn from(value: &[u8; 4]) -> Self {
49        FourCC(*value)
50    }
51}
52
53impl fmt::Display for FourCC {
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        let s = String::from_utf8_lossy(&self.0);
56        write!(f, "{s}")
57    }
58}
59
60impl fmt::Debug for FourCC {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        let s = String::from_utf8_lossy(&self.0);
63        write!(f, "{s}")
64    }
65}
66
67impl Encode for FourCC {
68    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
69        self.0.encode(buf)
70    }
71}
72
73impl Decode for FourCC {
74    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
75        Ok(FourCC(<[u8; 4]>::decode(buf)?))
76    }
77}
78
79impl AsRef<[u8; 4]> for FourCC {
80    fn as_ref(&self) -> &[u8; 4] {
81        &self.0
82    }
83}
84
85#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
86#[allow(non_camel_case_types)]
87#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
88pub struct u24([u8; 3]);
89
90impl u24 {
91    pub const MAX: u32 = 0x00FF_FFFF;
92}
93
94impl From<[u8; 3]> for u24 {
95    fn from(value: [u8; 3]) -> Self {
96        Self(value)
97    }
98}
99
100impl Decode for u24 {
101    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
102        Ok(Self(<[u8; 3]>::decode(buf)?))
103    }
104}
105
106impl Encode for u24 {
107    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
108        self.0.encode(buf)
109    }
110}
111
112impl From<u24> for u32 {
113    fn from(value: u24) -> Self {
114        u32::from_be_bytes([0, value.0[0], value.0[1], value.0[2]])
115    }
116}
117
118impl TryFrom<u32> for u24 {
119    type Error = std::array::TryFromSliceError;
120
121    fn try_from(value: u32) -> std::result::Result<Self, Self::Error> {
122        Ok(Self(value.to_be_bytes()[1..].try_into()?))
123    }
124}
125
126impl ToBytes for u24 {
127    type Bytes = [u8; 3];
128
129    fn to_be_bytes(&self) -> Self::Bytes {
130        self.0
131    }
132
133    fn to_le_bytes(&self) -> Self::Bytes {
134        [self.0[2], self.0[1], self.0[0]]
135    }
136}
137
138#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
139#[allow(non_camel_case_types)]
140#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
141pub struct u48([u8; 6]);
142
143impl Decode for u48 {
144    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
145        Ok(Self(<[u8; 6]>::decode(buf)?))
146    }
147}
148
149impl Encode for u48 {
150    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
151        self.0.encode(buf)
152    }
153}
154
155impl TryFrom<u64> for u48 {
156    type Error = std::array::TryFromSliceError;
157
158    fn try_from(value: u64) -> std::result::Result<Self, Self::Error> {
159        Ok(Self(value.to_be_bytes()[2..].try_into()?))
160    }
161}
162
163impl From<u48> for u64 {
164    fn from(value: u48) -> Self {
165        u64::from_be_bytes([
166            0, 0, value.0[0], value.0[1], value.0[2], value.0[3], value.0[4], value.0[5],
167        ])
168    }
169}
170
171impl From<[u8; 6]> for u48 {
172    fn from(value: [u8; 6]) -> Self {
173        u48(value)
174    }
175}
176
177impl AsRef<[u8; 6]> for u48 {
178    fn as_ref(&self) -> &[u8; 6] {
179        &self.0
180    }
181}
182
183// The top N bits are the integer part, the bottom N bits are the fractional part.
184// Somebody who cares should implement some math stuff.
185#[derive(Copy, Clone, Default, PartialEq, Eq)]
186#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
187pub struct FixedPoint<T> {
188    int: T,
189    dec: T,
190}
191
192impl<T: Copy> FixedPoint<T> {
193    pub fn new(int: T, dec: T) -> Self {
194        Self { int, dec }
195    }
196
197    pub fn integer(&self) -> T {
198        self.int
199    }
200
201    pub fn decimal(&self) -> T {
202        self.dec
203    }
204}
205
206impl<T: Decode> Decode for FixedPoint<T> {
207    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
208        Ok(Self {
209            int: T::decode(buf)?,
210            dec: T::decode(buf)?,
211        })
212    }
213}
214
215impl<T: Encode> Encode for FixedPoint<T> {
216    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
217        self.int.encode(buf)?;
218        self.dec.encode(buf)
219    }
220}
221
222impl<T: num::Zero> From<T> for FixedPoint<T> {
223    fn from(value: T) -> Self {
224        Self {
225            int: value,
226            dec: T::zero(),
227        }
228    }
229}
230
231impl<T> fmt::Debug for FixedPoint<T>
232where
233    T: num::Zero + fmt::Debug + PartialEq + Copy,
234    f64: From<T>,
235{
236    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
237        if self.dec.is_zero() {
238            write!(f, "{:?}", self.int)
239        } else {
240            write!(f, "{:?}", f64::from(self.int) / f64::from(self.dec))
241        }
242    }
243}
244
245// 32 bytes max
246#[derive(Debug, Clone, PartialEq, Eq, Default)]
247#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
248pub struct Compressor(String);
249
250impl From<&str> for Compressor {
251    fn from(value: &str) -> Self {
252        Self(value.to_string())
253    }
254}
255
256impl From<String> for Compressor {
257    fn from(value: String) -> Self {
258        Self(value)
259    }
260}
261
262impl From<Compressor> for String {
263    fn from(value: Compressor) -> Self {
264        value.0
265    }
266}
267
268impl AsRef<str> for Compressor {
269    fn as_ref(&self) -> &str {
270        &self.0
271    }
272}
273
274impl Encode for Compressor {
275    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
276        let name = self.0.as_bytes();
277        let len = name.len();
278        if len > 31 {
279            return Err(Error::InvalidSize);
280        }
281        (len as u8).encode(buf)?;
282        (&name[..len]).encode(buf)?;
283
284        let zero = [0u8; 31];
285        (&zero[..31 - len]).encode(buf)
286    }
287}
288
289impl Decode for Compressor {
290    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
291        let compressor_name_bytes = <[u8; 32]>::decode(buf)?;
292        match compressor_name_bytes[0] {
293            0 => Ok(Self(String::new())),
294            1..=31 => {
295                let start_bytes = 1;
296                let end_bytes = start_bytes + compressor_name_bytes[0] as usize;
297                let name = String::from_utf8_lossy(&compressor_name_bytes[start_bytes..end_bytes])
298                    .trim_end_matches('\0')
299                    .to_string();
300                Ok(Self(name))
301            }
302            _ => {
303                // try reading as a string
304                let name = String::from_utf8_lossy(&compressor_name_bytes)
305                    .trim_end_matches('\0')
306                    .to_string();
307                Ok(Self(name))
308            }
309        }
310    }
311}
312
313#[derive(Debug, Clone, PartialEq, Eq, Default)]
314#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
315pub struct Zeroed {
316    pub size: usize,
317}
318
319impl Zeroed {
320    pub fn new(size: usize) -> Self {
321        Self { size }
322    }
323}
324
325impl Encode for Zeroed {
326    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
327        let zero = [0u8; 32];
328        let mut size = self.size;
329
330        while size > 0 {
331            let len = zero.len().min(size);
332            (&zero[..len]).encode(buf)?;
333            size -= len;
334        }
335
336        Ok(())
337    }
338}
339
340impl Decode for Zeroed {
341    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
342        let size = buf.remaining();
343        buf.advance(size);
344        Ok(Self { size })
345    }
346}
347
348impl From<usize> for Zeroed {
349    fn from(size: usize) -> Self {
350        Self { size }
351    }
352}
353
354/// A 16-byte code used to identify UUID boxes.
355#[derive(Copy, Clone, Default, PartialEq, Eq)]
356#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
357pub struct ExtendedType([u8; 16]);
358
359impl ExtendedType {
360    pub const fn new(value: &[u8; 16]) -> Self {
361        ExtendedType(*value)
362    }
363}
364
365impl From<&[u8; 16]> for ExtendedType {
366    fn from(val: &[u8; 16]) -> ExtendedType {
367        ExtendedType(*val)
368    }
369}
370
371impl From<[u8; 16]> for ExtendedType {
372    fn from(val: [u8; 16]) -> ExtendedType {
373        ExtendedType(val)
374    }
375}
376
377impl From<ExtendedType> for [u8; 16] {
378    fn from(et: ExtendedType) -> [u8; 16] {
379        et.0
380    }
381}
382
383impl Encode for ExtendedType {
384    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
385        self.0.encode(buf)
386    }
387}
388impl Decode for ExtendedType {
389    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
390        Ok(ExtendedType(<[u8; 16]>::decode(buf)?))
391    }
392}
393
394impl fmt::Display for ExtendedType {
395    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
396        write!(f, "{:02x?}", self.0)
397    }
398}
399
400impl fmt::Debug for ExtendedType {
401    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402        write!(f, "{:02x?}", self.0)
403    }
404}
405
406impl AsRef<[u8; 16]> for ExtendedType {
407    fn as_ref(&self) -> &[u8; 16] {
408        &self.0
409    }
410}
411
412#[cfg(test)]
413mod tests {
414    use crate::{Compressor, Decode as _, Encode as _, ExtendedType};
415
416    #[test]
417    fn check_compressor_encode_minimal() {
418        let compressor = Compressor::from("A");
419        let mut buf = Vec::new();
420        compressor.encode(&mut buf).unwrap();
421        assert_eq!(buf.len(), 32);
422        assert_eq!(
423            buf,
424            vec![
425                0x01, b'A', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427                0x00, 0x00, 0x00, 0x00,
428            ]
429        );
430        let decode = Compressor::decode(&mut buf.as_ref()).unwrap();
431        assert_eq!(decode, compressor);
432    }
433
434    #[test]
435    fn check_compressor_encode_empty() {
436        let compressor = Compressor::from("");
437        let mut buf = Vec::new();
438        compressor.encode(&mut buf).unwrap();
439        assert_eq!(buf.len(), 32);
440        assert_eq!(
441            buf,
442            vec![
443                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445                0x00, 0x00, 0x00, 0x00,
446            ]
447        );
448        let decode = Compressor::decode(&mut buf.as_ref()).unwrap();
449        assert_eq!(decode, compressor);
450    }
451
452    #[test]
453    fn check_compressor_encode_maximal() {
454        let compressor = Compressor::from("ABCDEFGHIJKLMNOPQRSTUVWXYZabcde");
455        let mut buf = Vec::new();
456        compressor.encode(&mut buf).unwrap();
457        assert_eq!(buf.len(), 32);
458        assert_eq!(
459            buf,
460            vec![
461                0x1F, b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M',
462                b'N', b'O', b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X', b'Y', b'Z', b'a',
463                b'b', b'c', b'd', b'e'
464            ]
465        );
466        let decode = Compressor::decode(&mut buf.as_ref()).unwrap();
467        assert_eq!(decode, compressor);
468    }
469
470    #[test]
471    fn check_compressor_encode_too_long() {
472        let compressor = Compressor::from("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef");
473        let mut buf = Vec::new();
474        let result = compressor.encode(&mut buf);
475        assert!(result.is_err());
476    }
477
478    #[test]
479    fn test_extended_type_creation_and_conversion() {
480        let bytes: [u8; 16] = [
481            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
482            0x0e, 0x0f,
483        ];
484
485        let et_new = ExtendedType::new(&bytes);
486        let et_from = ExtendedType::from(bytes);
487        let et_ref_from = ExtendedType::from(&bytes);
488
489        assert_eq!(et_new, et_from);
490        assert_eq!(et_from, et_ref_from);
491
492        let output = <[u8; 16]>::from(et_new);
493
494        assert_eq!(bytes, output);
495    }
496}