1use crate::*;
2
3use std::fmt;
4use std::io::Read;
5
6macro_rules! any {
7 (basic: [$($kind:ident,)* $(,)?], boxed: [$($boxed:ident,)* $(,)?]) => {
8 #[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 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 remaining = buf.remaining();
43 let mut peek = buf.slice(remaining);
44 let header = match Header::decode_maybe(&mut peek)? {
45 Some(header) => header,
46 None => return Ok(None),
47 };
48
49 let size = header.size.unwrap_or(peek.remaining());
50 if size > peek.remaining() {
51 return Ok(None);
52 }
53
54 buf.advance(remaining - peek.remaining());
55 Ok(Some(Self::decode_atom(&header, buf)?))
56 }
57 }
58
59 impl Encode for Any {
60 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
61 buf.encode_atom(self.kind(), |buf| match self {
62 $(Any::$kind(inner) => Atom::encode_body(inner, buf),)*
63 $(Any::$boxed(boxed) => Atom::encode_body(boxed.as_ref(), buf),)*
64 Any::Unknown(_, data) => data.encode(buf),
65 })
66 }
67 }
68
69 impl DecodeAtom for Any {
70 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 $(_ if header.kind == $boxed::KIND => {
89 Any::$boxed(match $boxed::decode_body(&mut body) {
90 Ok(atom) => Box::new(atom),
91 Err(Error::OutOfBounds) => return Err(Error::OverDecode($boxed::KIND)),
92 Err(Error::ShortRead) => return Err(Error::UnderDecode($boxed::KIND)),
93 Err(err) => return Err(err),
94 })
95 },)*
96 _ => {
97 let body = Vec::decode(body)?;
98 Any::Unknown(header.kind, body)
99 },
100 };
101
102 if body.has_remaining() {
103 return Err(Error::UnderDecode(header.kind));
104 }
105
106 buf.advance(size);
107
108 Ok(atom)
109 }
110 }
111
112 impl fmt::Debug for Any {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 match self {
115 $(Any::$kind(inner) => inner.fmt(f),)*
116 $(Any::$boxed(boxed) => boxed.fmt(f),)*
117 Any::Unknown(kind, body) => write!(f, "Unknown {{ kind: {:?}, size: {:?}, bytes: {:?} }}", kind, body.len(), body),
118 }
119 }
120 }
121
122 $(impl From<$kind> for Any {
123 fn from(inner: $kind) -> Self {
124 Any::$kind(inner)
125 }
126 })*
127
128 $(impl From<$boxed> for Any {
129 fn from(inner: $boxed) -> Self {
130 Any::$boxed(Box::new(inner))
131 }
132 })*
133
134 $(impl TryFrom<Any> for $kind {
135 type Error = Any;
136
137 fn try_from(any: Any) -> std::result::Result<Self, Any> {
138 match any {
139 Any::$kind(inner) => Ok(inner),
140 _ => Err(any),
141 }
142 }
143 })*
144
145 $(impl TryFrom<Any> for $boxed {
146 type Error = Any;
147
148 fn try_from(any: Any) -> std::result::Result<Self, Any> {
149 match any {
150 Any::$boxed(boxed) => Ok(*boxed),
151 _ => Err(any),
152 }
153 }
154 })*
155
156 $(impl From<Box<$boxed>> for $boxed {
158 fn from(boxed: Box<$boxed>) -> Self {
159 *boxed
160 }
161 })*
162
163 pub trait AnyAtom: Atom {
166 fn from_any(any: Any) -> Option<Self>;
167 fn from_any_ref(any: &Any) -> Option<&Self>;
168 fn from_any_mut(any: &mut Any) -> Option<&mut Self>;
169
170 fn into_any(self) -> Any;
171 }
172
173 $(impl AnyAtom for $kind {
174 fn from_any(any: Any) -> Option<Self> {
175 match any {
176 Any::$kind(inner) => Some(inner),
177 _ => None,
178 }
179 }
180
181 fn from_any_ref(any: &Any) -> Option<&Self> {
182 match any {
183 Any::$kind(inner) => Some(inner),
184 _ => None,
185 }
186 }
187
188 fn from_any_mut(any: &mut Any) -> Option<&mut Self> {
189 match any {
190 Any::$kind(inner) => Some(inner),
191 _ => None,
192 }
193 }
194
195 fn into_any(self) -> Any {
196 Any::$kind(self)
197 }
198 })*
199
200 $(impl AnyAtom for $boxed {
201 fn from_any(any: Any) -> Option<Self> {
202 match any {
203 Any::$boxed(boxed) => Some(*boxed),
204 _ => None,
205 }
206 }
207
208 fn from_any_ref(any: &Any) -> Option<&Self> {
209 match any {
210 Any::$boxed(boxed) => Some(boxed),
211 _ => None,
212 }
213 }
214
215 fn from_any_mut(any: &mut Any) -> Option<&mut Self> {
216 match any {
217 Any::$boxed(boxed) => Some(boxed),
218 _ => None,
219 }
220 }
221
222 fn into_any(self) -> Any {
223 Any::$boxed(Box::new(self))
224 }
225 })*
226 };
227}
228
229any! {
230 basic: [
231 Ftyp,
232 Styp,
233 Meta,
234 Hdlr,
235 Pitm,
236 Iloc,
237 Iinf,
238 Iprp,
239 Ipco,
240 Auxc,
241 Clap,
242 Imir,
243 Irot,
244 Iscl,
245 Ispe,
246 Pixi,
247 Rref,
248 Ipma,
249 Iref,
250 Idat,
251 Ilst,
252 Covr,
253 Desc,
254 Tool, Name,
256 Rtng,
257 Year,
258 Keys,
259 Moov,
260 Mvhd,
261 Ainf,
262 Udta,
263 Cprt,
264 Kind,
265 Skip,
266 Tkhd,
268 Mdia,
269 Mdhd,
270 Minf,
271 Stbl,
272 Stsd,
273 Avc1, Avc3,
274 Avcc,
275 Btrt,
276 Ccst,
277 Colr,
278 Pasp,
279 Taic,
280 Fiel,
281 Jpeg,
282 Hev1, Hvc1,
283 Hvcc, Lhvc,
284 Mp4a,
285 Esds,
286 Mp3,
287 Tx3g,
288 Ftab,
289 Vp08, Vp09,
290 VpcC,
291 Av01,
292 Av1c,
293 Opus,
294 Dops,
295 Uncv,
296 Cmpd,
297 UncC,
298 Flac,
299 Dfla,
300 Ac3,
301 Ac3SpecificBox,
302 Eac3,
303 Ec3SpecificBox,
304 Sowt, Twos, Lpcm, Ipcm, Fpcm, In24, In32, Fl32, Fl64, S16l,
305 PcmC,
306 Chnl,
307 Wvtt,
308 VttC,
309 Vlab,
310 Samr,
311 Damr,
312 Mett,
313 TxtC,
314 Metx,
315 Urim,
316 Uri,
317 UriI,
318 Camm,
319 Evte,
320 Silb,
321 Mebx,
322 Keyd,
323 Dtyp,
324 Loca,
325 Setu,
326 Stts,
327 Stsc,
328 Stsz,
329 Stss,
330 Stco,
331 Co64,
332 Cslg,
333 Ctts,
334 Sbgp,
335 Sgpd,
336 Subs,
337 Saio,
338 Saiz,
339 Dinf,
340 Dref,
341 Hmhd,
342 Nmhd,
343 Smhd,
344 Sthd,
345 Vmhd,
346 Edts,
347 Elst,
348 Tref,
349 Mvex,
350 Mehd,
351 Trex,
352 Emsg,
353 Moof,
354 Mfhd,
355 Traf,
356 Tfhd,
357 Tfdt,
358 Trun,
359 Senc,
360 Mdat,
361 Free,
362 Sidx,
363 Prft,
364 Mfra,
365 Tfra,
366 Mfro,
367 Uuid,
368 ],
369 boxed: [
370 Trak,
371 ]
372}
373
374impl ReadFrom for Any {
375 fn read_from<R: Read + ?Sized>(r: &mut R) -> Result<Self> {
376 <Option<Any> as ReadFrom>::read_from(r)?.ok_or(Error::UnexpectedEof)
377 }
378}
379
380impl ReadFrom for Option<Any> {
381 fn read_from<R: Read + ?Sized>(r: &mut R) -> Result<Self> {
382 let header = match <Option<Header> as ReadFrom>::read_from(r)? {
383 Some(header) => header,
384 None => return Ok(None),
385 };
386
387 let body = &mut header.read_body(r)?;
388 Ok(Some(Any::decode_atom(&header, body)?))
389 }
390}
391
392impl ReadAtom for Any {
393 fn read_atom<R: Read + ?Sized>(header: &Header, r: &mut R) -> Result<Self> {
394 let body = &mut header.read_body(r)?;
395 Any::decode_atom(header, body)
396 }
397}
398
399#[cfg(test)]
400mod tests {
401 use super::*;
402
403 const PARTIAL_FTYP: &[u8] = b"\0\0\0\x14ftypisom";
404
405 #[test]
406 fn decode_maybe_preserves_incomplete_atom() {
407 let mut buf = PARTIAL_FTYP;
408
409 assert!(Any::decode_maybe(&mut buf).unwrap().is_none());
410 assert_eq!(buf, PARTIAL_FTYP);
411 }
412}