1
2
3#[macro_export]
4macro_rules! base_box {
5 (box ($id:expr, $name:ident, $box:ident) $(data { $($data_name:ident: $data:ty),* $(,)* })? $(children { $($child_name:ident: $($child:ident)+),* $(,)*})?) => {
6 pub type $box = $crate::mp4box::box_root::MP4Box<$name>;
7
8 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
9 pub struct $name {
10 $($(pub $data_name: $data,)*)?
11 $($(pub $child_name: base_box!(@type $($child)+)),*)?
12 }
13
14
15 impl $crate::mp4box::box_trait::PartialBox for $name {
16 type ParentData = ();
17 type ThisData = ();
18
19 fn byte_size(&self) -> usize {
20 #![allow(unused_imports)]
21 use $crate::mp4box::box_trait::IBox;
22 use $crate::bytes_write::Mp4Writable;
23 $($(self.$data_name.byte_size() +)*)?
24 $($(self.$child_name.byte_size() +)*)? 0
25 }
26
27 const ID: $crate::r#type::BoxType = $crate::r#type::BoxType::Id($crate::id::BoxId(*$id));
28 }
29
30 #[allow(unused_variables, unused_mut, dead_code, unused_imports)]
31 #[async_trait::async_trait]
32 impl $crate::mp4box::box_trait::PartialBoxRead for $name{
33 async fn read_data<R: $crate::bytes_read::ReadMp4>(_: Self::ParentData, reader: &mut R) -> Result<Self, $crate::error::MP4Error> {
34 Ok(Self {
35 $($($data_name: reader.read().await?,)*)?
36 $($($child_name: Default::default(),)*)?
37 })
38 }
39
40 async fn read_child<R: $crate::bytes_read::ReadMp4>(&mut self, header: $crate::header::BoxHeader, reader: &mut R) -> Result<(), $crate::error::MP4Error> {
41 #![allow(unused_imports)]
42 use $crate::mp4box::box_trait::IBox;
43 use $crate::mp4box::box_trait::BoxRead;
44 match header.id {
45 $($(base_box!(@id $($child)+) => base_box!(@read self.$child_name, header, reader, $($child)+),)*)?
46 _ => {}
47 }
48 Ok(())
49 }
50 }
51
52 #[allow(unused_variables, unused_mut, dead_code, unused_imports)]
53 impl $crate::mp4box::box_trait::PartialBoxWrite for $name {
54
55 fn write_data<W: $crate::bytes_write::WriteMp4>(&self, writer: &mut W) -> Result<usize, $crate::error::MP4Error> {
56 let mut count = 0;
57 use $crate::bytes_write::Mp4Writable;
58 $($(count += self.$data_name.write(writer)?;)*)?
59 Ok(count)
60 }
61
62
63 fn write_children<W: $crate::bytes_write::WriteMp4>(&self, writer: &mut W) -> Result<usize, $crate::error::MP4Error> {
64 #![allow(unused_imports)]
65 use $crate::mp4box::box_trait::BoxWrite;
66 let mut count = 0;
67 $($(count += self.$child_name.write(writer)?;)*)?
68 Ok(count)
69 }
70 }
71
72 };
73
74 (@type vec $child:ty) => {
75 Vec<$child>
76 };
77
78 (@type $child:ty) => {
79 Option<$child>
80 };
81
82 (@id vec $child:ty) => {
83 <$child>::ID
84 };
85
86 (@id $child:ty) => {
87 <$child>::ID
88 };
89
90 (@read $child_name:expr, $header:ident, $reader:ident, vec $child:ty) => {
91 $child_name.push(<$child>::read($header, $reader).await?)
92 };
93
94 (@read $child_name:expr, $header:ident, $reader:ident, $child:ty) => {
95 $child_name = Some(<$child>::read($header, $reader).await?)
96 };
97}
98
99
100#[macro_export]
101macro_rules! full_box {
102 (box ($id:expr, $name:ident, $box:ident, $(@save $flag_name:ident :)? $flag:ty) $(data { $($data_name:ident: $data:ty),* $(,)* })? $(children { $($child_name:ident: $($child:ident)+),* $(,)*})?) => {
103 pub type $box = $crate::mp4box::box_root::MP4Box<$crate::mp4box::box_full::FullBox<$name, $flag>>;
104
105 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
106 pub struct $name {
107 $($(pub $data_name: $data,)*)?
108 $(pub $flag_name: $flag,)?
109 $($(pub $child_name: base_box!(@type $($child)+)),*)?
110 }
111
112 impl $crate::mp4box::box_full::FullBoxInfo for $name {
113 type Flag = $flag;
114
115 fn version(&self) -> u8 {
116 #![allow(unused_imports)]
117 use $crate::bytes_write::Mp4VersionedWritable;
118 $crate::max!(
119 $($(Mp4VersionedWritable::<$flag>::required_version(&self.$data_name)),*)?
120 )
121 }
122
123 fn flags(&self) -> $flag {
124 #![allow(unused_imports)]
125 use $crate::bytes_write::Mp4VersionedWritable;
126 $($(Mp4VersionedWritable::<$flag>::required_flags(&self.$data_name) |)*)? $(self.$flag_name |)? <$flag>::default()
127 }
128 }
129
130 impl $crate::mp4box::box_trait::PartialBox for $name {
131 type ParentData = $crate::mp4box::box_full::FullBoxData<$flag>;
132 type ThisData = ();
133
134 fn byte_size(&self) -> usize {
135 #![allow(unused_imports)]
136 use $crate::mp4box::box_trait::IBox;
137 use $crate::mp4box::box_full::FullBoxInfo;
138 use $crate::bytes_write::Mp4VersionedWritable;
139 let version = self.version();
140 let flags = self.flags();
141 $($(self.$data_name.versioned_byte_size(version, flags) +)*)?
142 $($(self.$child_name.byte_size() +)*)? 0
143 }
144
145 const ID: $crate::r#type::BoxType = $crate::r#type::BoxType::Id($crate::id::BoxId(*$id));
146 }
147
148 #[allow(unused_variables, unused_mut, dead_code, unused_imports)]
149 #[async_trait::async_trait]
150 impl $crate::mp4box::box_trait::PartialBoxRead for $name {
151
152 async fn read_data<R: $crate::bytes_read::ReadMp4>(parent: Self::ParentData, reader: &mut R) -> Result<Self, $crate::error::MP4Error> {
153 let version = parent.version;
154 let flags = parent.flags;
155 Ok(Self {
156 $($flag_name: flags,)?
157 $($($data_name: reader.versioned_read(version, flags).await?,)*)?
158 $($($child_name: Default::default(),)*)?
159 })
160 }
161
162 async fn read_child<R: $crate::bytes_read::ReadMp4>(&mut self, header: $crate::header::BoxHeader, reader: &mut R) -> Result<(), $crate::error::MP4Error> {
163 #![allow(unused_imports)]
164 use $crate::mp4box::box_trait::IBox;
165 use $crate::mp4box::box_trait::BoxRead;
166 match header.id {
167 $($(base_box!(@id $($child)+) => base_box!(@read self.$child_name, header, reader, $($child)+),)*)?
168 _ => {}
169 }
170 Ok(())
171 }
172 }
173
174 #[allow(unused_variables, unused_mut, dead_code, unused_imports)]
175 impl $crate::mp4box::box_trait::PartialBoxWrite for $name {
176
177 fn write_data<W: $crate::bytes_write::WriteMp4>(&self, writer: &mut W) -> Result<usize, $crate::error::MP4Error> {
178 #![allow(unused_imports)]
179 use $crate::bytes_write::Mp4VersionedWritable;
180 use $crate::mp4box::box_full::FullBoxInfo;
181 let version = self.version();
182 let flags = self.flags();
183 let mut count = 0;
184 $($(count += self.$data_name.versioned_write(version, flags, writer)?;)*)?
185 Ok(count)
186 }
187
188 fn write_children<W: $crate::bytes_write::WriteMp4>(&self, writer: &mut W) -> Result<usize, $crate::error::MP4Error> {
189 #![allow(unused_imports)]
190 use $crate::mp4box::box_trait::BoxWrite;
191 let mut count = 0;
192 $($(count += self.$child_name.write(writer)?;)*)?
193 Ok(count)
194 }
195 }
196
197 };
198
199 (@type vec $child:ty) => {
200 Vec<$child>
201 };
202
203 (@type $child:ty) => {
204 Option<$child>
205 };
206
207 (@id vec $child:ty) => {
208 <$child>::ID
209 };
210
211 (@id $child:ty) => {
212 <$child>::ID
213 };
214
215 (@read $child_name:expr, $header:ident, $reader:ident, $version:ident, $flags:ident, vec $child:ty) => {
216 $child_name.push(<$child>::read($header, $reader).await?)
217 };
218
219 (@read $child_name:expr, $header:ident, $reader:ident, $child:ty) => {
220 $child_name = Some(<$child>::read($header, $reader).await?)
221 };
222}
223
224
225#[macro_export]
226macro_rules! default_flags {
227 ($name:ident, $default:expr) => {
228 #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
229 pub struct $name(pub u32);
230
231 impl Default for VmhdFlags {
232 fn default() -> Self {
233 Self($default)
234 }
235 }
236
237 impl From<u32> for VmhdFlags {
238 fn from(value: u32) -> Self {
239 Self(value)
240 }
241 }
242
243 impl std::ops::BitOr for VmhdFlags {
244 type Output = Self;
245
246 fn bitor(self, rhs: Self) -> Self::Output {
247 Self(self.0 | rhs.0)
248 }
249 }
250
251 impl From<VmhdFlags> for u32 {
252 fn from(value: VmhdFlags) -> Self {
253 value.0
254 }
255 }
256 }
257}
258
259
260#[macro_export]
261macro_rules! mp4_data {
262 ($(#[$attr:meta])* $vis:vis struct $name:ident { $($v:vis $data_name:ident: $data:ty),* $(,)* }) => {
263
264 $(#[$attr])*
265 $vis struct $name {
266 $($v $data_name: $data,)*
267 }
268
269 #[allow(unused_variables, unused_mut, dead_code)]
270 #[async_trait::async_trait]
271 impl $crate::bytes_read::Mp4Readable for $name {
272 async fn read<R: $crate::bytes_read::ReadMp4>(reader: &mut R) -> Result<Self, $crate::error::MP4Error> {
273 Ok(Self {
274 $($data_name: reader.read().await?,)*
275 })
276 }
277 }
278
279 #[allow(unused_variables, unused_mut, dead_code)]
280 impl $crate::bytes_write::Mp4Writable for $name {
281 fn byte_size(&self) -> usize {
282 let mut count = 0;
283 $(count += self.$data_name.byte_size();)*
284 count
285 }
286
287 fn write<W: $crate::bytes_write::WriteMp4>(&self, writer: &mut W) -> Result<usize, $crate::error::MP4Error> {
288 let mut count = 0;
289 $(count += self.$data_name.write(writer)?;)*
290 Ok(count)
291 }
292 }
293
294 };
295
296 ($(#[$attr:meta])* $vis:vis struct $name:ident ($($v:vis $data:ty),* $(,)* );) => {
297
298 $(#[$attr])*
299 $vis struct $name (
300 $($v $data,)*
301 );
302
303 #[allow(unused_variables, unused_mut, dead_code)]
304 #[async_trait::async_trait]
305 impl $crate::bytes_read::Mp4Readable for $name {
306 async fn read<R: $crate::bytes_read::ReadMp4>(reader: &mut R) -> Result<Self, $crate::error::MP4Error> {
307 Ok(Self (
308 $(reader.read::<$data>().await?,)*
309 ))
310 }
311 }
312
313 #[allow(unused_variables, unused_mut, dead_code)]
314 impl $crate::bytes_write::Mp4Writable for $name {
315 fn byte_size(&self) -> usize {
316 let mut count = 0;
317 mp4_data!(@bytes count, self, $($data),*);
318 count
319 }
320
321 fn write<W: $crate::bytes_write::WriteMp4>(&self, writer: &mut W) -> Result<usize, $crate::error::MP4Error> {
322 let mut count = 0;
323 mp4_data!(@write count, self, writer, $($data),*);
324 Ok(count)
325 }
326 }
327 };
328
329 (@bytes $count:ident, $self:ident) => {};
330
331 (@bytes $count:ident, $self:ident, $data:ty) => {
332 $count += $self.0.byte_size();
333 };
334
335 (@bytes $count:ident, $self:ident, $data:ty, $data2:ty) => {
336 mp4_data!(@bytes $count, $data);
337 $count += $self.1.byte_size();
338 };
339
340 (@bytes $count:ident, $self:ident, $data:ty, $data2:ty, $data3:ty) => {
341 mp4_data!(@bytes $count, $data, $data2);
342 $count += $self.2.byte_size();
343 };
344 (@bytes $count:ident, $self:ident, $data:ty, $data2:ty, $data3:ty, $data4:ty) => {
345 mp4_data!(@bytes $count, $data, $data2, $data3);
346 $count += $self.3.byte_size();
347 };
348
349 (@write $count:ident, $self:ident, $writer:ident) => {};
350
351 (@write $count:ident, $self:ident, $writer:ident, $data:ty) => {
352 $count += $self.0.write($writer)?;
353 };
354
355 (@write $count:ident, $self:ident, $writer:ident, $data:ty, $data2:ty) => {
356 mp4_data!(@bytes $count, $data);
357 $count += $self.1.write($writer)?;
358 };
359
360 (@write $count:ident, $self:ident, $writer:ident, $data:ty, $data2:ty, $data3:ty) => {
361 mp4_data!(@bytes $count, $data, $data2);
362 $count += $self.2.write($writer)?;
363 };
364 (@write $count:ident, $self:ident, $writer:ident, $data:ty, $data2:ty, $data3:ty, $data4:ty) => {
365 mp4_data!(@bytes $count, $data, $data2, $data3);
366 $count += $self.3.write($writer)?;
367 };
368}
369
370#[macro_export]
371macro_rules! mp4_versioned_data {
372 ($(#[$attr:meta])* $vis:vis struct $name:ident { $($v:vis $data_name:ident: $data:ty),* $(,)* }) => {
373
374 $(#[$attr])*
375 $vis struct $name {
376 $($v $data_name: $data,)*
377 }
378
379 #[allow(unused_variables, unused_mut, dead_code)]
380 #[async_trait::async_trait]
381 impl<F: $crate::bytes_write::FlagTrait> $crate::bytes_read::Mp4VersionedReadable<F> for $name where $($data: $crate::bytes_read::Mp4VersionedReadable<F>),* {
382 async fn versioned_read<R: $crate::bytes_read::ReadMp4>(version: u8, flags: F, reader: &mut R) -> Result<Self, $crate::error::MP4Error> {
383 Ok(Self {
384 $($data_name: reader.versioned_read(version, flags).await?,)*
385 })
386 }
387 }
388
389 #[allow(unused_variables, unused_mut, dead_code)]
390 impl<F: $crate::bytes_write::FlagTrait> $crate::bytes_write::Mp4VersionedWritable<F> for $name where $($data: $crate::bytes_write::Mp4VersionedWritable<F>),* {
391
392 fn required_version(&self) -> u8 {
393 $crate::max!($(self.$data_name.required_version()),*)
394 }
395
396 fn required_flags(&self) -> F {
397 $(self.$data_name.required_flags() | )* F::default()
398 }
399
400 fn versioned_byte_size(&self, version: u8, flags: F) -> usize {
401 let mut count = 0;
402 $(count += self.$data_name.versioned_byte_size(version, flags);)*
403 count
404 }
405
406 fn versioned_write<W: $crate::bytes_write::WriteMp4>(&self, version: u8, flags: F, writer: &mut W) -> Result<usize, $crate::error::MP4Error> {
407 let mut count = 0;
408 $(count += self.$data_name.versioned_write(version, flags, writer)?;)*
409 Ok(count)
410 }
411 }
412
413 };
414
415 ($(#[$attr:meta])* $vis:vis struct $name:ident ($($v:vis $data:ty),* $(,)* );) => {
416
417 $(#[$attr])*
418 $vis struct $name (
419 $($v $data,)*
420 );
421
422 #[allow(unused_variables, unused_mut, dead_code)]
423 #[async_trait::async_trait]
424 impl<F: $crate::bytes_write::FlagTrait> $crate::bytes_read::Mp4Readable for $name {
425 async fn versioned_read<R: $crate::bytes_read::ReadMp4>(version: u8, flags: F, reader: &mut R) -> Result<Self, $crate::error::MP4Error> {
426 Ok(Self (
427 $(reader.read_versioned::<$data>(version, flags).await?,)*
428 ))
429 }
430 }
431
432 #[allow(unused_variables, unused_mut, dead_code)]
433 #[async_trait::async_trait]
434 impl<F: $crate::bytes_write::FlagTrait> $crate::bytes_write::Mp4Writable for $name {
435 fn versioned_byte_size(&self, version: u8, flags: F) -> usize {
436 let mut count = 0;
437 mp4_versioned_data!(@bytes count, self, version, flags, $($data),*);
438 count
439 }
440
441 fn versioned_write<W: $crate::bytes_write::WriteMp4>(&self, version: u8, flags: F, writer: &mut W) -> Result<usize, $crate::error::MP4Error> {
442 let mut count = 0;
443 mp4_versioned_data!(@write count, self, version, flags, writer, $($data),*);
444 Ok(count)
445 }
446 }
447 };
448
449 (@bytes $count:ident, $self:ident, $version:ident, $flags:ident) => {};
450
451 (@bytes $count:ident, $self:ident, $version:ident, $flags:ident, $data:ty) => {
452 $count += $self.0.versioned_byte_size($version, $flags);
453 };
454
455 (@bytes $count:ident, $self:ident, $version:ident, $flags:ident, $data:ty, $data2:ty) => {
456 mp4_data!(@bytes $count, $data);
457 $count += $self.1.versioned_byte_size($version, $flags);
458 };
459
460 (@bytes $count:ident, $self:ident, $version:ident, $flags:ident, $data:ty, $data2:ty, $data3:ty) => {
461 mp4_data!(@bytes $count, $data, $data2);
462 $count += $self.2.versioned_byte_size($version, $flags);
463 };
464 (@bytes $count:ident, $self:ident, $version:ident, $flags:ident, $data:ty, $data2:ty, $data3:ty, $data4:ty) => {
465 mp4_data!(@bytes $count, $data, $data2, $data3);
466 $count += $self.3.versioned_byte_size($version, $flags);
467 };
468
469 (@write $count:ident, $self:ident, $version:ident, $flags:ident, $writer:ident) => {};
470
471 (@write $count:ident, $self:ident, $version:ident, $flags:ident, $writer:ident, $data:ty) => {
472 $count += $self.0.versioned_write($version, $flags, $writer)?;
473 };
474
475 (@write $count:ident, $self:ident, $version:ident, $flags:ident, $writer:ident, $data:ty, $data2:ty) => {
476 mp4_data!(@bytes $count, $data);
477 $count += $self.1.versioned_write($version, $flags, $writer)?;
478 };
479
480 (@write $count:ident, $self:ident, $version:ident, $flags:ident, $writer:ident, $data:ty, $data2:ty, $data3:ty) => {
481 mp4_data!(@bytes $count, $data, $data2);
482 $count += $self.2.versioned_write($version, $flags, $writer)?;
483 };
484 (@write $count:ident, $self:ident, $version:ident, $flags:ident, $writer:ident, $data:ty, $data2:ty, $data3:ty, $data4:ty) => {
485 mp4_data!(@bytes $count, $data, $data2, $data3);
486 $count += $self.3.versioned_write($version, $flags, $writer)?;
487 };
488}
489
490#[macro_export]
491macro_rules! flag_option {
492 ($(#[$attr:meta])* $vis:vis struct $name:ident ($v:vis $data:ty, $flag:ty, $value:ident);) => {
493 $(#[$attr])*
494 $vis struct $name (
495 $v Option<$data>
496 );
497
498
499 impl std::ops::Deref for $name {
500 type Target = Option<$data>;
501
502 fn deref(&self) -> &Self::Target {
503 &self.0
504 }
505 }
506
507 impl From<$data> for $name {
508 fn from(t: $data) -> Self {
509 Self(Some(t))
510 }
511 }
512
513 impl From<Option<$data>> for $name {
514 fn from(t: Option<$data>) -> Self {
515 Self(t)
516 }
517 }
518
519 paste::paste! {
520 #[async_trait::async_trait]
521 impl $crate::bytes_read::Mp4VersionedReadable<$flag> for $name {
522 async fn versioned_read<R: $crate::bytes_read::ReadMp4>(version: u8, flags: $flag, reader: &mut R) -> Result<Self, $crate::error::MP4Error> {
523 Ok(Self(if flags.[<$value:lower>]() { Some(reader.versioned_read(version, flags).await?) } else { None }))
524 }
525 }
526
527 impl $crate::bytes_write::Mp4VersionedWritable<$flag> for $name {
528 fn required_flags(&self) -> $flag {
529 match self.0 { None => <$flag>::default(), Some(_) => <$flag>::[<with_ $value:lower>]() }
530 }
531
532 fn versioned_byte_size(&self, version: u8, flags: $flag) -> usize {
533 if flags.[<$value:lower>]() { self.0.unwrap_or_default().versioned_byte_size(version, flags) } else { 0 }
534 }
535
536 fn versioned_write<W: $crate::bytes_write::WriteMp4>(&self, version: u8, flags: $flag, writer: &mut W) -> Result<usize, $crate::error::MP4Error> {
537 Ok(if flags.[<$value:lower>]() { self.0.unwrap_or_default().versioned_write(version, flags, writer)? } else { 0 })
538 }
539 }
540 }
541 };
542}
543
544#[macro_export]
545macro_rules! max {
546 ($x:expr) => ( $x );
547 ($x:expr, $($xs:expr),+) => {
548 {
549 use std::cmp::max;
550 max($x, $crate::max!($($xs),+ ))
551 }
552 };
553}
554
555#[macro_export]
556macro_rules! min {
557 ($x:expr) => ( $x );
558 ($x:expr, $($xs:expr),+) => {
559 {
560 use std::cmp::min;
561 min($x, $crate::min!($($xs),+ ))
562 }
563 };
564}