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