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 Disp,
289 Ftab,
290 Vp08, Vp09,
291 VpcC,
292 Av01,
293 Av1c,
294 Opus,
295 Dops,
296 Uncv,
297 Cmpd,
298 UncC,
299 Flac,
300 Dfla,
301 Ac3,
302 Ac3SpecificBox,
303 Eac3,
304 Ec3SpecificBox,
305 Sowt, Twos, Lpcm, Ipcm, Fpcm, In24, In32, Fl32, Fl64, S16l,
306 PcmC,
307 Chnl,
308 Wvtt,
309 VttC,
310 Vlab,
311 Samr,
312 Damr,
313 Mett,
314 TxtC,
315 Metx,
316 Urim,
317 Uri,
318 UriI,
319 Camm,
320 Evte,
321 Silb,
322 Mebx,
323 Keyd,
324 Dtyp,
325 Loca,
326 Setu,
327 Stts,
328 Stsc,
329 Stsz,
330 Stss,
331 Stco,
332 Co64,
333 Cslg,
334 Ctts,
335 Sbgp,
336 Sgpd,
337 Subs,
338 Saio,
339 Saiz,
340 Dinf,
341 Dref,
342 Hmhd,
343 Nmhd,
344 Smhd,
345 Sthd,
346 Vmhd,
347 Edts,
348 Elst,
349 Tref,
350 Mvex,
351 Mehd,
352 Trex,
353 Emsg,
354 Moof,
355 Mfhd,
356 Traf,
357 Tfhd,
358 Tfdt,
359 Trun,
360 Senc,
361 Mdat,
362 Free,
363 Sidx,
364 Prft,
365 Mfra,
366 Tfra,
367 Mfro,
368 Uuid,
369 ],
370 boxed: [
371 Trak,
372 ]
373}
374
375impl ReadFrom for Any {
376 fn read_from<R: Read + ?Sized>(r: &mut R) -> Result<Self> {
377 <Option<Any> as ReadFrom>::read_from(r)?.ok_or(Error::UnexpectedEof)
378 }
379}
380
381impl ReadFrom for Option<Any> {
382 fn read_from<R: Read + ?Sized>(r: &mut R) -> Result<Self> {
383 let header = match <Option<Header> as ReadFrom>::read_from(r)? {
384 Some(header) => header,
385 None => return Ok(None),
386 };
387
388 let body = &mut header.read_body(r)?;
389 Ok(Some(Any::decode_atom(&header, body)?))
390 }
391}
392
393impl ReadAtom for Any {
394 fn read_atom<R: Read + ?Sized>(header: &Header, r: &mut R) -> Result<Self> {
395 let body = &mut header.read_body(r)?;
396 Any::decode_atom(header, body)
397 }
398}
399
400#[cfg(test)]
401mod tests {
402 use super::*;
403
404 const PARTIAL_FTYP: &[u8] = b"\0\0\0\x14ftypisom";
405
406 #[test]
407 fn decode_maybe_preserves_incomplete_atom() {
408 let mut buf = PARTIAL_FTYP;
409
410 assert!(Any::decode_maybe(&mut buf).unwrap().is_none());
411 assert_eq!(buf, PARTIAL_FTYP);
412 }
413}