mp4_atom/
any.rs

1use crate::*;
2
3use std::fmt;
4use std::io::Read;
5
6macro_rules! any {
7    ($($kind:ident,)*) => {
8        /// Any of the supported atoms.
9        #[derive(Clone, PartialEq)]
10        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11        pub enum Any {
12            $($kind($kind),)*
13            Unknown(FourCC, Vec<u8>),
14        }
15
16        impl Any {
17            /// Get the kind of the atom.
18            pub fn kind(&self) -> FourCC {
19                match self {
20                    $(Any::$kind(_) => $kind::KIND,)*
21                    Any::Unknown(kind, _) => *kind,
22                }
23            }
24        }
25
26        impl Decode for Any {
27            fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
28                match Self::decode_maybe(buf)? {
29                    Some(any) => Ok(any),
30                    None => Err(Error::OutOfBounds),
31                }
32            }
33        }
34
35        impl DecodeMaybe for Any {
36            fn decode_maybe<B: Buf>(buf: &mut B) -> Result<Option<Self>> {
37                let header = match Header::decode_maybe(buf)? {
38                    Some(header) => header,
39                    None => return Ok(None),
40                };
41
42                let size = header.size.unwrap_or(buf.remaining());
43                if size > buf.remaining() {
44                    return Ok(None);
45                }
46
47                Ok(Some(Self::decode_atom(&header, buf)?))
48            }
49        }
50
51        impl Encode for Any {
52            fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
53                let start = buf.len();
54                0u32.encode(buf)?;
55                self.kind().encode(buf)?;
56
57                match self {
58                    $(Any::$kind(inner) => Atom::encode_body(inner, buf),)*
59                    Any::Unknown(_, data) => data.encode(buf),
60                }?;
61
62                let size: u32 = (buf.len() - start).try_into().map_err(|_| Error::TooLarge(self.kind()))?;
63                buf.set_slice(start, &size.to_be_bytes());
64
65                Ok(())
66            }
67        }
68
69        impl DecodeAtom for Any {
70            /// Decode the atom from a header and payload.
71            fn decode_atom<B: Buf>(header: &Header, buf: &mut B) -> Result<Self> {
72                let size = header.size.unwrap_or(buf.remaining());
73                if size > buf.remaining() {
74                    return Err(Error::OutOfBounds);
75                }
76
77                let mut body = &mut buf.slice(size);
78
79                let atom = match header.kind {
80                    $(_ if header.kind == $kind::KIND => {
81                        Any::$kind(match $kind::decode_body(&mut body) {
82                            Ok(atom) => atom,
83                            Err(Error::OutOfBounds) => return Err(Error::OverDecode($kind::KIND)),
84                            Err(Error::ShortRead) => return Err(Error::UnderDecode($kind::KIND)),
85                            Err(err) => return Err(err),
86                        })
87                    },)*
88                    _ => {
89                        let body = Vec::decode(body)?;
90                        Any::Unknown(header.kind, body)
91                    },
92                };
93
94                if body.has_remaining() {
95                    return Err(Error::UnderDecode(header.kind));
96                }
97
98                buf.advance(size);
99
100                Ok(atom)
101            }
102        }
103
104        impl fmt::Debug for Any {
105            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106                match self {
107                    $(Any::$kind(inner) => inner.fmt(f),)*
108                    Any::Unknown(kind, body) => write!(f, "Unknown {{ kind: {:?}, size: {:?} }}", kind, body.len()),
109                }
110            }
111        }
112
113        $(impl From<$kind> for Any {
114            fn from(inner: $kind) -> Self {
115                Any::$kind(inner)
116            }
117        })*
118    };
119}
120
121any! {
122    Ftyp,
123    Styp,
124    Moov,
125        Mvhd,
126        Udta,
127            Meta,
128                Ilst,
129                    Covr,
130                    Desc,
131                    Name,
132                    Year,
133            Skip,
134        Trak,
135            Tkhd,
136            Mdia,
137                Mdhd,
138                Hdlr,
139                Minf,
140                    Stbl,
141                        Stsd,
142                            Avc1,
143                                Avcc,
144                            Hev1,
145                                Hvcc,
146                            Mp4a,
147                                Esds,
148                            Tx3g,
149                            Vp09,
150                        Stts,
151                        Stsc,
152                        Stsz,
153                        Stss,
154                        Stco,
155                        Co64,
156                        Ctts,
157                    Dinf,
158                        Dref,
159                    Smhd,
160                    Vmhd,
161            Edts,
162                Elst,
163        Mvex,
164            Mehd,
165            Trex,
166    Emsg,
167    Moof,
168        Mfhd,
169        Traf,
170            Tfhd,
171            Tfdt,
172            Trun,
173    Mdat,
174    Free,
175}
176
177impl ReadFrom for Any {
178    fn read_from<R: Read>(r: &mut R) -> Result<Self> {
179        <Option<Any> as ReadFrom>::read_from(r)?.ok_or(Error::UnexpectedEof)
180    }
181}
182
183impl ReadFrom for Option<Any> {
184    fn read_from<R: Read>(r: &mut R) -> Result<Self> {
185        let header = match <Option<Header> as ReadFrom>::read_from(r)? {
186            Some(header) => header,
187            None => return Ok(None),
188        };
189
190        let body = &mut header.read_body(r)?;
191        Ok(Some(Any::decode_atom(&header, body)?))
192    }
193}
194
195impl ReadAtom for Any {
196    fn read_atom<R: Read>(header: &Header, r: &mut R) -> Result<Self> {
197        let body = &mut header.read_body(r)?;
198        Any::decode_atom(header, body)
199    }
200}