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 Moov,
268 Mvhd,
269 Ainf,
270 Udta,
271 Cprt,
272 Kind,
273 Skip,
274 Tkhd,
276 Mdia,
277 Mdhd,
278 Minf,
279 Stbl,
280 Stsd,
281 Avc1,
282 Avcc,
283 Btrt,
284 Ccst,
285 Colr,
286 Pasp,
287 Taic,
288 Fiel,
289 Hev1, Hvc1,
290 Hvcc, Lhvc,
291 Mp4a,
292 Esds,
293 Tx3g,
294 Ftab,
295 Vp08, Vp09,
296 VpcC,
297 Av01,
298 Av1c,
299 Opus,
300 Dops,
301 Uncv,
302 Cmpd,
303 UncC,
304 Flac,
305 Dfla,
306 Ac3,
307 Ac3SpecificBox,
308 Eac3,
309 Ec3SpecificBox,
310 Sowt, Twos, Lpcm, Ipcm, Fpcm, In24, In32, Fl32, Fl64, S16l,
311 PcmC,
312 Chnl,
313 Wvtt,
314 VttC,
315 Vlab,
316 Samr,
317 Damr,
318 Stts,
319 Stsc,
320 Stsz,
321 Stss,
322 Stco,
323 Co64,
324 Cslg,
325 Ctts,
326 Sbgp,
327 Sgpd,
328 Subs,
329 Saio,
330 Saiz,
331 Dinf,
332 Dref,
333 Hmhd,
334 Nmhd,
335 Smhd,
336 Sthd,
337 Vmhd,
338 Edts,
339 Elst,
340 Tref,
341 Mvex,
342 Mehd,
343 Trex,
344 Emsg,
345 Moof,
346 Mfhd,
347 Traf,
348 Tfhd,
349 Tfdt,
350 Trun,
351 Senc,
352 Mdat,
353 Free,
354 Sidx,
355 Prft,
356 Mfra,
357 Tfra,
358 Mfro,
359 ],
360 boxed: [
361 Trak,
362 ]
363}
364
365impl ReadFrom for Any {
366 fn read_from<R: Read + ?Sized>(r: &mut R) -> Result<Self> {
367 <Option<Any> as ReadFrom>::read_from(r)?.ok_or(Error::UnexpectedEof)
368 }
369}
370
371impl ReadFrom for Option<Any> {
372 fn read_from<R: Read + ?Sized>(r: &mut R) -> Result<Self> {
373 let header = match <Option<Header> as ReadFrom>::read_from(r)? {
374 Some(header) => header,
375 None => return Ok(None),
376 };
377
378 let body = &mut header.read_body(r)?;
379 Ok(Some(Any::decode_atom(&header, body)?))
380 }
381}
382
383impl ReadAtom for Any {
384 fn read_atom<R: Read + ?Sized>(header: &Header, r: &mut R) -> Result<Self> {
385 let body = &mut header.read_body(r)?;
386 Any::decode_atom(header, body)
387 }
388}
389
390#[cfg(test)]
391mod tests {
392 use super::*;
393
394 const PARTIAL_FTYP: &[u8] = b"\0\0\0\x14ftypisom";
395
396 #[test]
397 fn decode_maybe_preserves_incomplete_atom() {
398 let mut buf = PARTIAL_FTYP;
399
400 assert!(Any::decode_maybe(&mut buf).unwrap().is_none());
401 assert_eq!(buf, PARTIAL_FTYP);
402 }
403}