mp4_atom/
any.rs

1use crate::*;
2
3use std::fmt;
4use std::io::Read;
5
6macro_rules! any {
7    (basic: [$($kind:ident,)* $(,)?], boxed: [$($boxed:ident,)* $(,)?]) => {
8        /// Any of the supported atoms.
9        #[derive(Clone, PartialEq)]
10        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11        #[non_exhaustive]
12        pub enum Any {
13            $($kind($kind),)*
14            $($boxed(Box<$boxed>),)*
15            Unknown(FourCC, Vec<u8>),
16        }
17
18        impl Any {
19            /// Get the kind of the atom.
20            pub fn kind(&self) -> FourCC {
21                match self {
22                    $(Any::$kind(_) => $kind::KIND,)*
23                    $(Any::$boxed(_) => $boxed::KIND,)*
24                    Any::Unknown(kind, _) => *kind,
25                }
26            }
27        }
28
29        impl Decode for Any {
30            fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
31                match Self::decode_maybe(buf)? {
32                    Some(any) => Ok(any),
33                    None => Err(Error::OutOfBounds),
34                }
35            }
36        }
37
38        impl DecodeMaybe for Any {
39            fn decode_maybe<B: Buf>(buf: &mut B) -> Result<Option<Self>> {
40                let header = match Header::decode_maybe(buf)? {
41                    Some(header) => header,
42                    None => return Ok(None),
43                };
44
45                let size = header.size.unwrap_or(buf.remaining());
46                if size > buf.remaining() {
47                    return Ok(None);
48                }
49
50                Ok(Some(Self::decode_atom(&header, buf)?))
51            }
52        }
53
54        impl Encode for Any {
55            fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
56                let start = buf.len();
57                0u32.encode(buf)?;
58                self.kind().encode(buf)?;
59
60                match self {
61                    $(Any::$kind(inner) => Atom::encode_body(inner, buf),)*
62                    $(Any::$boxed(boxed) => Atom::encode_body(boxed.as_ref(), buf),)*
63                    Any::Unknown(_, data) => data.encode(buf),
64                }?;
65
66                let size: u32 = (buf.len() - start).try_into().map_err(|_| Error::TooLarge(self.kind()))?;
67                buf.set_slice(start, &size.to_be_bytes());
68
69                Ok(())
70            }
71        }
72
73        impl DecodeAtom for Any {
74            /// Decode the atom from a header and payload.
75            fn decode_atom<B: Buf>(header: &Header, buf: &mut B) -> Result<Self> {
76                let size = header.size.unwrap_or(buf.remaining());
77                if size > buf.remaining() {
78                    return Err(Error::OutOfBounds);
79                }
80
81                let mut body = &mut buf.slice(size);
82
83                let atom = match header.kind {
84                    $(_ if header.kind == $kind::KIND => {
85                        Any::$kind(match $kind::decode_body(&mut body) {
86                            Ok(atom) => atom,
87                            Err(Error::OutOfBounds) => return Err(Error::OverDecode($kind::KIND)),
88                            Err(Error::ShortRead) => return Err(Error::UnderDecode($kind::KIND)),
89                            Err(err) => return Err(err),
90                        })
91                    },)*
92                    $(_ if header.kind == $boxed::KIND => {
93                        Any::$boxed(match $boxed::decode_body(&mut body) {
94                            Ok(atom) => Box::new(atom),
95                            Err(Error::OutOfBounds) => return Err(Error::OverDecode($boxed::KIND)),
96                            Err(Error::ShortRead) => return Err(Error::UnderDecode($boxed::KIND)),
97                            Err(err) => return Err(err),
98                        })
99                    },)*
100                    _ => {
101                        let body = Vec::decode(body)?;
102                        Any::Unknown(header.kind, body)
103                    },
104                };
105
106                if body.has_remaining() {
107                    return Err(Error::UnderDecode(header.kind));
108                }
109
110                buf.advance(size);
111
112                Ok(atom)
113            }
114        }
115
116        impl fmt::Debug for Any {
117            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118                match self {
119                    $(Any::$kind(inner) => inner.fmt(f),)*
120                    $(Any::$boxed(boxed) => boxed.fmt(f),)*
121                    Any::Unknown(kind, body) => write!(f, "Unknown {{ kind: {:?}, size: {:?}, bytes: {:?} }}", kind, body.len(), body),
122                }
123            }
124        }
125
126        $(impl From<$kind> for Any {
127            fn from(inner: $kind) -> Self {
128                Any::$kind(inner)
129            }
130        })*
131
132        $(impl From<$boxed> for Any {
133            fn from(inner: $boxed) -> Self {
134                Any::$boxed(Box::new(inner))
135            }
136        })*
137
138        $(impl TryFrom<Any> for $kind {
139            type Error = Any;
140
141            fn try_from(any: Any) -> std::result::Result<Self, Any> {
142                match any {
143                    Any::$kind(inner) => Ok(inner),
144                    _ => Err(any),
145                }
146            }
147        })*
148
149        $(impl TryFrom<Any> for $boxed {
150            type Error = Any;
151
152            fn try_from(any: Any) -> std::result::Result<Self, Any> {
153                match any {
154                    Any::$boxed(boxed) => Ok(*boxed),
155                    _ => Err(any),
156                }
157            }
158        })*
159
160        // So we can use .into() to automatically unbox
161        $(impl From<Box<$boxed>> for $boxed {
162            fn from(boxed: Box<$boxed>) -> Self {
163                *boxed
164            }
165        })*
166
167        /// A trait to help casting to/from Any.
168        /// From/TryFrom use concrete types, but if we want to use generics, then we need a trait.
169        pub trait AnyAtom: Atom {
170            fn from_any(any: Any) -> Option<Self>;
171            fn from_any_ref(any: &Any) -> Option<&Self>;
172            fn from_any_mut(any: &mut Any) -> Option<&mut Self>;
173
174            fn into_any(self) -> Any;
175        }
176
177        $(impl AnyAtom for $kind {
178            fn from_any(any: Any) -> Option<Self> {
179                match any {
180                    Any::$kind(inner) => Some(inner),
181                    _ => None,
182                }
183            }
184
185            fn from_any_ref(any: &Any) -> Option<&Self> {
186                match any {
187                    Any::$kind(inner) => Some(inner),
188                    _ => None,
189                }
190            }
191
192            fn from_any_mut(any: &mut Any) -> Option<&mut Self> {
193                match any {
194                    Any::$kind(inner) => Some(inner),
195                    _ => None,
196                }
197            }
198
199            fn into_any(self) -> Any {
200                Any::$kind(self)
201            }
202        })*
203
204        $(impl AnyAtom for $boxed {
205            fn from_any(any: Any) -> Option<Self> {
206                match any {
207                    Any::$boxed(boxed) => Some(*boxed),
208                    _ => None,
209                }
210            }
211
212            fn from_any_ref(any: &Any) -> Option<&Self> {
213                match any {
214                    Any::$boxed(boxed) => Some(boxed),
215                    _ => None,
216                }
217            }
218
219            fn from_any_mut(any: &mut Any) -> Option<&mut Self> {
220                match any {
221                    Any::$boxed(boxed) => Some(boxed),
222                    _ => None,
223                }
224            }
225
226            fn into_any(self) -> Any {
227                Any::$boxed(Box::new(self))
228            }
229        })*
230    };
231}
232
233any! {
234    basic: [
235    Ftyp,
236    Styp,
237    Meta,
238        Hdlr,
239        Pitm,
240        Iloc,
241        Iinf,
242        Iprp,
243            Ipco,
244                Auxc,
245                Clap,
246                Imir,
247                Irot,
248                Iscl,
249                Ispe,
250                Pixi,
251                Rref,
252            Ipma,
253        Iref,
254        Idat,
255        Ilst,
256            Covr,
257            Desc,
258            Name,
259            Year,
260    Moov,
261        Mvhd,
262        Udta,
263            Skip,
264        // Trak, // boxed to avoid large size differences between variants
265            Tkhd,
266            Mdia,
267                Mdhd,
268                Minf,
269                    Stbl,
270                        Stsd,
271                            Avc1,
272                                Avcc,
273                                Btrt,
274                                Ccst,
275                                Colr,
276                                Pasp,
277                                Taic,
278                            Hev1, Hvc1,
279                                Hvcc,
280                            Mp4a,
281                                Esds,
282                            Tx3g,
283                            Vp08, Vp09,
284                                VpcC,
285                            Av01,
286                                Av1c,
287                            Opus,
288                                Dops,
289                            Uncv,
290                                Cmpd,
291                                UncC,
292                            Flac,
293                                Dfla,
294                            Ac3,
295                                Ac3SpecificBox,
296                            Eac3,
297                                Ec3SpecificBox,
298                        Stts,
299                        Stsc,
300                        Stsz,
301                        Stss,
302                        Stco,
303                        Co64,
304                        Ctts,
305                        Sbgp,
306                        Sgpd,
307                        Subs,
308                        Saio,
309                        Saiz,
310                    Dinf,
311                        Dref,
312                    Smhd,
313                    Vmhd,
314            Edts,
315                Elst,
316        Mvex,
317            Mehd,
318            Trex,
319    Emsg,
320    Moof,
321        Mfhd,
322        Traf,
323            Tfhd,
324            Tfdt,
325            Trun,
326    Mdat,
327    Free,
328    ],
329    boxed: [
330        Trak,
331    ]
332}
333
334impl ReadFrom for Any {
335    fn read_from<R: Read>(r: &mut R) -> Result<Self> {
336        <Option<Any> as ReadFrom>::read_from(r)?.ok_or(Error::UnexpectedEof)
337    }
338}
339
340impl ReadFrom for Option<Any> {
341    fn read_from<R: Read>(r: &mut R) -> Result<Self> {
342        let header = match <Option<Header> as ReadFrom>::read_from(r)? {
343            Some(header) => header,
344            None => return Ok(None),
345        };
346
347        let body = &mut header.read_body(r)?;
348        Ok(Some(Any::decode_atom(&header, body)?))
349    }
350}
351
352impl ReadAtom for Any {
353    fn read_atom<R: Read>(header: &Header, r: &mut R) -> Result<Self> {
354        let body = &mut header.read_body(r)?;
355        Any::decode_atom(header, body)
356    }
357}