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            Tool, // "©too"
259            Name,
260            Year,
261    Moov,
262        Mvhd,
263        Udta,
264            Cprt,
265            Kind,
266            Skip,
267        // Trak, // boxed to avoid large size differences between variants
268            Tkhd,
269            Mdia,
270                Mdhd,
271                Minf,
272                    Stbl,
273                        Stsd,
274                            Avc1,
275                                Avcc,
276                                Btrt,
277                                Ccst,
278                                Colr,
279                                Pasp,
280                                Taic,
281                                Fiel,
282                            Hev1, Hvc1,
283                                Hvcc,
284                            Mp4a,
285                                Esds,
286                            Tx3g,
287                                Ftab,
288                            Vp08, Vp09,
289                                VpcC,
290                            Av01,
291                                Av1c,
292                            Opus,
293                                Dops,
294                            Uncv,
295                                Cmpd,
296                                UncC,
297                            Flac,
298                                Dfla,
299                            Ac3,
300                                Ac3SpecificBox,
301                            Eac3,
302                                Ec3SpecificBox,
303                            Sowt, Twos, Lpcm, Ipcm, Fpcm, In24, In32, Fl32, Fl64, S16l,
304                                PcmC,
305                                Chnl,
306                        Stts,
307                        Stsc,
308                        Stsz,
309                        Stss,
310                        Stco,
311                        Co64,
312                        Cslg,
313                        Ctts,
314                        Sbgp,
315                        Sgpd,
316                        Subs,
317                        Saio,
318                        Saiz,
319                    Dinf,
320                        Dref,
321                    Nmhd,
322                    Smhd,
323                    Sthd,
324                    Vmhd,
325            Edts,
326                Elst,
327        Mvex,
328            Mehd,
329            Trex,
330    Emsg,
331    Moof,
332        Mfhd,
333        Traf,
334            Tfhd,
335            Tfdt,
336            Trun,
337            Senc,
338    Mdat,
339    Free,
340    Sidx,
341    Prft,
342    Mfra,
343        Tfra,
344        Mfro,
345    ],
346    boxed: [
347        Trak,
348    ]
349}
350
351impl ReadFrom for Any {
352    fn read_from<R: Read>(r: &mut R) -> Result<Self> {
353        <Option<Any> as ReadFrom>::read_from(r)?.ok_or(Error::UnexpectedEof)
354    }
355}
356
357impl ReadFrom for Option<Any> {
358    fn read_from<R: Read>(r: &mut R) -> Result<Self> {
359        let header = match <Option<Header> as ReadFrom>::read_from(r)? {
360            Some(header) => header,
361            None => return Ok(None),
362        };
363
364        let body = &mut header.read_body(r)?;
365        Ok(Some(Any::decode_atom(&header, body)?))
366    }
367}
368
369impl ReadAtom for Any {
370    fn read_atom<R: Read>(header: &Header, r: &mut R) -> Result<Self> {
371        let body = &mut header.read_body(r)?;
372        Any::decode_atom(header, body)
373    }
374}