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