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 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 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 $(impl From<Box<$boxed>> for $boxed {
162 fn from(boxed: Box<$boxed>) -> Self {
163 *boxed
164 }
165 })*
166
167 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, Name,
260 Rtng,
261 Year,
262 Moov,
263 Mvhd,
264 Ainf,
265 Udta,
266 Cprt,
267 Kind,
268 Skip,
269 Tkhd,
271 Mdia,
272 Mdhd,
273 Minf,
274 Stbl,
275 Stsd,
276 Avc1,
277 Avcc,
278 Btrt,
279 Ccst,
280 Colr,
281 Pasp,
282 Taic,
283 Fiel,
284 Hev1, Hvc1,
285 Hvcc, Lhvc,
286 Mp4a,
287 Esds,
288 Tx3g,
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 Stts,
314 Stsc,
315 Stsz,
316 Stss,
317 Stco,
318 Co64,
319 Cslg,
320 Ctts,
321 Sbgp,
322 Sgpd,
323 Subs,
324 Saio,
325 Saiz,
326 Dinf,
327 Dref,
328 Hmhd,
329 Nmhd,
330 Smhd,
331 Sthd,
332 Vmhd,
333 Edts,
334 Elst,
335 Tref,
336 Mvex,
337 Mehd,
338 Trex,
339 Emsg,
340 Moof,
341 Mfhd,
342 Traf,
343 Tfhd,
344 Tfdt,
345 Trun,
346 Senc,
347 Mdat,
348 Free,
349 Sidx,
350 Prft,
351 Mfra,
352 Tfra,
353 Mfro,
354 ],
355 boxed: [
356 Trak,
357 ]
358}
359
360impl ReadFrom for Any {
361 fn read_from<R: Read + ?Sized>(r: &mut R) -> Result<Self> {
362 <Option<Any> as ReadFrom>::read_from(r)?.ok_or(Error::UnexpectedEof)
363 }
364}
365
366impl ReadFrom for Option<Any> {
367 fn read_from<R: Read + ?Sized>(r: &mut R) -> Result<Self> {
368 let header = match <Option<Header> as ReadFrom>::read_from(r)? {
369 Some(header) => header,
370 None => return Ok(None),
371 };
372
373 let body = &mut header.read_body(r)?;
374 Ok(Some(Any::decode_atom(&header, body)?))
375 }
376}
377
378impl ReadAtom for Any {
379 fn read_atom<R: Read + ?Sized>(header: &Header, r: &mut R) -> Result<Self> {
380 let body = &mut header.read_body(r)?;
381 Any::decode_atom(header, body)
382 }
383}