async_mp4/mp4box/
box_macro.rs

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}