1use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
60use bytes::Buf;
61use std::io::Write;
62use std::{convert::TryInto, marker::PhantomData};
63use tokio::io::{AsyncRead, AsyncReadExt};
64
65use crate::*;
66
67pub(crate) mod avc1;
68pub(crate) mod co64;
69pub(crate) mod ctts;
70pub(crate) mod data;
71pub(crate) mod dinf;
72pub(crate) mod edts;
73pub(crate) mod elst;
74pub(crate) mod emsg;
75pub(crate) mod ftyp;
76pub(crate) mod hdlr;
77pub(crate) mod hev1;
78pub(crate) mod ilst;
79pub(crate) mod mdhd;
80pub(crate) mod mdia;
81pub(crate) mod mehd;
82pub(crate) mod meta;
83pub(crate) mod mfhd;
84pub(crate) mod minf;
85pub(crate) mod moof;
86pub(crate) mod moov;
87pub(crate) mod mp4a;
88pub(crate) mod mvex;
89pub(crate) mod mvhd;
90pub(crate) mod smhd;
91pub(crate) mod stbl;
92pub(crate) mod stco;
93pub(crate) mod stsc;
94pub(crate) mod stsd;
95pub(crate) mod stss;
96pub(crate) mod stsz;
97pub(crate) mod stts;
98pub(crate) mod tfdt;
99pub(crate) mod tfhd;
100pub(crate) mod tkhd;
101pub(crate) mod traf;
102pub(crate) mod trak;
103pub(crate) mod trex;
104pub(crate) mod trun;
105pub(crate) mod tx3g;
106pub(crate) mod udta;
107pub(crate) mod vmhd;
108pub(crate) mod vp09;
109pub(crate) mod vpcc;
110
111pub use avc1::Avc1Box;
112pub use co64::Co64Box;
113pub use ctts::CttsBox;
114pub use data::DataBox;
115pub use dinf::DinfBox;
116pub use edts::EdtsBox;
117pub use elst::ElstBox;
118pub use emsg::EmsgBox;
119pub use ftyp::FtypBox;
120pub use hdlr::HdlrBox;
121pub use hev1::Hev1Box;
122pub use ilst::IlstBox;
123pub use mdhd::MdhdBox;
124pub use mdia::MdiaBox;
125pub use mehd::MehdBox;
126pub use meta::MetaBox;
127pub use mfhd::MfhdBox;
128pub use minf::MinfBox;
129pub use moof::MoofBox;
130pub use moov::MoovBox;
131pub use mp4a::Mp4aBox;
132pub use mvex::MvexBox;
133pub use mvhd::MvhdBox;
134pub use smhd::SmhdBox;
135pub use stbl::StblBox;
136pub use stco::StcoBox;
137pub use stsc::StscBox;
138pub use stsd::StsdBox;
139pub use stss::StssBox;
140pub use stsz::StszBox;
141pub use stts::SttsBox;
142pub use tfdt::TfdtBox;
143pub use tfhd::TfhdBox;
144pub use tkhd::TkhdBox;
145pub use traf::TrafBox;
146pub use trak::TrakBox;
147pub use trex::TrexBox;
148pub use trun::TrunBox;
149pub use tx3g::Tx3gBox;
150pub use udta::UdtaBox;
151pub use vmhd::VmhdBox;
152pub use vp09::Vp09Box;
153pub use vpcc::VpccBox;
154
155pub const HEADER_SIZE: u64 = 8;
156pub const HEADER_EXT_SIZE: u64 = 4;
158
159macro_rules! boxtype {
160 ($( $name:ident => $value:expr ),*) => {
161 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
162 pub enum BoxType {
163 $( $name, )*
164 UnknownBox(u32),
165 }
166
167 impl BoxType {
168 pub const fn as_str(&self) -> &'static str {
169 match self {
170 $( BoxType::$name => stringify!($name), )*
171 BoxType::UnknownBox(_) => "unknown",
172 }
173 }
174 }
175
176 impl From<u32> for BoxType {
177 fn from(t: u32) -> BoxType {
178 match t {
179 $( $value => BoxType::$name, )*
180 _ => BoxType::UnknownBox(t),
181 }
182 }
183 }
184
185 impl From<BoxType> for u32 {
186 fn from(b: BoxType) -> u32 {
187 match b {
188 $( BoxType::$name => $value, )*
189 BoxType::UnknownBox(t) => t,
190 }
191 }
192 }
193 }
194}
195
196boxtype! {
197 FtypBox => 0x66747970,
198 MvhdBox => 0x6d766864,
199 MfhdBox => 0x6d666864,
200 FreeBox => 0x66726565,
201 MdatBox => 0x6d646174,
202 MoovBox => 0x6d6f6f76,
203 MvexBox => 0x6d766578,
204 MehdBox => 0x6d656864,
205 TrexBox => 0x74726578,
206 EmsgBox => 0x656d7367,
207 MoofBox => 0x6d6f6f66,
208 TkhdBox => 0x746b6864,
209 TfhdBox => 0x74666864,
210 TfdtBox => 0x74666474,
211 EdtsBox => 0x65647473,
212 MdiaBox => 0x6d646961,
213 ElstBox => 0x656c7374,
214 MdhdBox => 0x6d646864,
215 HdlrBox => 0x68646c72,
216 MinfBox => 0x6d696e66,
217 VmhdBox => 0x766d6864,
218 StblBox => 0x7374626c,
219 StsdBox => 0x73747364,
220 SttsBox => 0x73747473,
221 CttsBox => 0x63747473,
222 StssBox => 0x73747373,
223 StscBox => 0x73747363,
224 StszBox => 0x7374737A,
225 StcoBox => 0x7374636F,
226 Co64Box => 0x636F3634,
227 TrakBox => 0x7472616b,
228 TrafBox => 0x74726166,
229 TrunBox => 0x7472756E,
230 UdtaBox => 0x75647461,
231 MetaBox => 0x6d657461,
232 DinfBox => 0x64696e66,
233 DrefBox => 0x64726566,
234 UrlBox => 0x75726C20,
235 SmhdBox => 0x736d6864,
236 Avc1Box => 0x61766331,
237 AvcCBox => 0x61766343,
238 Hev1Box => 0x68657631,
239 HvcCBox => 0x68766343,
240 Mp4aBox => 0x6d703461,
241 EsdsBox => 0x65736473,
242 Tx3gBox => 0x74783367,
243 VpccBox => 0x76706343,
244 Vp09Box => 0x76703039,
245 DataBox => 0x64617461,
246 IlstBox => 0x696c7374,
247 NameBox => 0xa96e616d,
248 DayBox => 0xa9646179,
249 CovrBox => 0x636f7672,
250 DescBox => 0x64657363,
251 WideBox => 0x77696465,
252 WaveBox => 0x77617665
253}
254
255pub trait Mp4Box: Sized {
256 const TYPE: BoxType;
257
258 fn box_size(&self) -> u64;
259 fn to_json(&self) -> Result<String, Error>;
260 fn summary(&self) -> Result<String, Error>;
261}
262
263pub struct BoxReader<'a, R: Reader<'a>> {
264 kind: BoxType,
265 inner: R,
266 m: PhantomData<&'a ()>,
267}
268
269impl<'a, R: Reader<'a>> BoxReader<'a, R> {
270 #[inline]
271 pub fn try_read<T: Mp4Box + BlockReader>(&mut self) -> Result<Option<T>, Error> {
272 if T::TYPE == self.kind {
273 Ok(Some(T::read_block(&mut self.inner)?))
274 } else {
275 Ok(None)
276 }
277 }
278
279 #[inline]
280 pub fn read<T: Mp4Box + BlockReader>(&mut self) -> Result<T, Error> {
281 if T::TYPE == self.kind {
282 T::read_block(&mut self.inner)
283 } else {
284 Err(Error::BoxNotFound(T::TYPE))
285 }
286 }
287}
288
289pub trait Reader<'a> {
290 fn take(&mut self, size: usize) -> Result<impl Reader<'a> + '_, Error>;
291 fn remaining(&self) -> usize;
292 fn skip(&mut self, size: usize);
293
294 fn peek_u32(&self) -> u32;
295
296 fn get_u8(&mut self) -> u8;
297 fn get_u16(&mut self) -> u16;
298 fn get_u24(&mut self) -> u32;
299 fn get_u32(&mut self) -> u32;
300 fn get_u48(&mut self) -> u64;
301 fn get_u64(&mut self) -> u64;
302
303 fn get_i8(&mut self) -> i8;
304 fn get_i16(&mut self) -> i16;
305 fn get_i24(&mut self) -> i32;
306 fn get_i32(&mut self) -> i32;
307 fn get_i48(&mut self) -> i64;
308 fn get_i64(&mut self) -> i64;
309
310 #[inline]
311 fn try_get_u8(&mut self) -> Result<u8, Error> {
312 if self.remaining() < 1 {
313 Err(Error::InvalidData("expected at least 1 byte more"))
314 } else {
315 Ok(self.get_u8())
316 }
317 }
318 #[inline]
319 fn try_get_u16(&mut self) -> Result<u16, Error> {
320 if self.remaining() < 2 {
321 Err(Error::InvalidData("expected at least 2 byte more"))
322 } else {
323 Ok(self.get_u16())
324 }
325 }
326 #[inline]
327 fn try_get_u24(&mut self) -> Result<u32, Error> {
328 if self.remaining() < 3 {
329 Err(Error::InvalidData("expected at least 3 byte more"))
330 } else {
331 Ok(self.get_u24())
332 }
333 }
334 #[inline]
335 fn try_get_u32(&mut self) -> Result<u32, Error> {
336 if self.remaining() < 4 {
337 Err(Error::InvalidData("expected at least 4 byte more"))
338 } else {
339 Ok(self.get_u32())
340 }
341 }
342 #[inline]
343 fn try_get_u48(&mut self) -> Result<u64, Error> {
344 if self.remaining() < 6 {
345 Err(Error::InvalidData("expected at least 6 byte more"))
346 } else {
347 Ok(self.get_u48())
348 }
349 }
350 #[inline]
351 fn try_get_u64(&mut self) -> Result<u64, Error> {
352 if self.remaining() < 8 {
353 Err(Error::InvalidData("expected at least 8 byte more"))
354 } else {
355 Ok(self.get_u64())
356 }
357 }
358
359 #[inline]
360 fn try_get_i8(&mut self) -> Result<i8, Error> {
361 if self.remaining() < 1 {
362 Err(Error::InvalidData("expected at least 1 byte more"))
363 } else {
364 Ok(self.get_i8())
365 }
366 }
367 #[inline]
368 fn try_get_i16(&mut self) -> Result<i16, Error> {
369 if self.remaining() < 2 {
370 Err(Error::InvalidData("expected at least 2 byte more"))
371 } else {
372 Ok(self.get_i16())
373 }
374 }
375 #[inline]
376 fn try_get_i24(&mut self) -> Result<i32, Error> {
377 if self.remaining() < 3 {
378 Err(Error::InvalidData("expected at least 3 byte more"))
379 } else {
380 Ok(self.get_i24())
381 }
382 }
383 #[inline]
384 fn try_get_i32(&mut self) -> Result<i32, Error> {
385 if self.remaining() < 4 {
386 Err(Error::InvalidData("expected at least 4 byte more"))
387 } else {
388 Ok(self.get_i32())
389 }
390 }
391 #[inline]
392 fn try_get_i48(&mut self) -> Result<i64, Error> {
393 if self.remaining() < 6 {
394 Err(Error::InvalidData("expected at least 6 byte more"))
395 } else {
396 Ok(self.get_i48())
397 }
398 }
399 #[inline]
400 fn try_get_i64(&mut self) -> Result<i64, Error> {
401 if self.remaining() < 8 {
402 Err(Error::InvalidData("expected at least 8 byte more"))
403 } else {
404 Ok(self.get_i64())
405 }
406 }
407 fn get_null_terminated_string(&mut self) -> String;
408 fn collect(&mut self, size: usize) -> Result<Vec<u8>, Error> {
409 let mut buf = vec![0; size];
410 self.copy_to_slice(&mut buf)?;
411
412 Ok(buf)
413 }
414
415 #[inline]
416 fn collect_remaining(&mut self) -> Vec<u8> {
417 self.collect(self.remaining()).unwrap()
418 }
419
420 fn copy_to_slice(&mut self, slice: &mut [u8]) -> Result<(), Error>;
421 fn get_box(&mut self) -> Result<Option<BoxReader<'a, impl Reader<'a> + '_>>, Error>;
422
423 fn find_box<B: Mp4Box + BlockReader>(&mut self) -> Result<B, Error> {
424 self.try_find_box()
425 .and_then(|x| x.ok_or(Error::InvalidData("expected box")))
426 }
427
428 fn try_find_box2<A: Mp4Box + BlockReader, B: Mp4Box + BlockReader>(
429 &mut self,
430 ) -> Result<(Option<A>, Option<B>), Error> {
431 let mut a = None;
432 let mut b = None;
433
434 while let Some(mut bx) = self.get_box()? {
435 if a.is_none() {
436 if let Some(inner) = bx.try_read::<A>()? {
437 a = Some(inner);
438 continue;
439 }
440 }
441
442 if b.is_none() {
443 if let Some(inner) = bx.try_read::<B>()? {
444 b = Some(inner);
445 continue;
446 }
447 }
448
449 println!(" 1 unknown box {}", bx.kind);
450 }
451
452 Ok((a, b))
453 }
454
455 fn try_find_box3<A, B, C>(&mut self) -> Result<(Option<A>, Option<B>, Option<C>), Error>
456 where
457 A: Mp4Box + BlockReader,
458 B: Mp4Box + BlockReader,
459 C: Mp4Box + BlockReader,
460 {
461 let mut a = None;
462 let mut b = None;
463 let mut c = None;
464
465 while let Some(mut bx) = self.get_box()? {
466 if a.is_none() {
467 if let Some(inner) = bx.try_read::<A>()? {
468 a = Some(inner);
469 continue;
470 }
471 }
472 if b.is_none() {
473 if let Some(inner) = bx.try_read::<B>()? {
474 b = Some(inner);
475 continue;
476 }
477 }
478
479 if c.is_none() {
480 if let Some(inner) = bx.try_read::<C>()? {
481 c = Some(inner);
482 continue;
483 }
484 }
485
486 println!(" 2 unknown box {}", bx.kind);
487 }
488
489 Ok((a, b, c))
490 }
491
492 #[inline]
493 fn find_box3<A, B, C>(&mut self) -> Result<(A, B, C), Error>
494 where
495 A: Mp4Box + BlockReader,
496 B: Mp4Box + BlockReader,
497 C: Mp4Box + BlockReader,
498 {
499 let (a, b, c) = self.try_find_box3()?;
500
501 let Some(a) = a else {
502 return Err(Error::BoxNotFound(A::TYPE));
503 };
504
505 let Some(b) = b else {
506 return Err(Error::BoxNotFound(B::TYPE));
507 };
508
509 let Some(c) = c else {
510 return Err(Error::BoxNotFound(C::TYPE));
511 };
512
513 Ok((a, b, c))
514 }
515
516 fn try_find_box4<A, B, C, D>(
517 &mut self,
518 ) -> Result<(Option<A>, Option<B>, Option<C>, Option<D>), Error>
519 where
520 A: Mp4Box + BlockReader,
521 B: Mp4Box + BlockReader,
522 C: Mp4Box + BlockReader,
523 D: Mp4Box + BlockReader,
524 {
525 let mut a = None;
526 let mut b = None;
527 let mut c = None;
528 let mut d = None;
529
530 while let Some(mut bx) = self.get_box()? {
531 if a.is_none() {
532 if let Some(inner) = bx.try_read::<A>()? {
533 a = Some(inner);
534 continue;
535 }
536 }
537
538 if b.is_none() {
539 if let Some(inner) = bx.try_read::<B>()? {
540 b = Some(inner);
541 continue;
542 }
543 }
544
545 if c.is_none() {
546 if let Some(inner) = bx.try_read::<C>()? {
547 c = Some(inner);
548 continue;
549 }
550 }
551
552 if d.is_none() {
553 if let Some(inner) = bx.try_read::<D>()? {
554 d = Some(inner);
555 continue;
556 }
557 }
558
559 println!(" 3 unknown box {}", bx.kind);
560 }
561
562 Ok((a, b, c, d))
563 }
564
565 #[inline]
566 fn try_find_box<B: Mp4Box + BlockReader>(&mut self) -> Result<Option<B>, Error> {
567 while let Some(mut bx) = self.get_box()? {
568 if let Some(inner) = bx.try_read::<B>()? {
569 return Ok(Some(inner));
570 }
571
572 println!(" 4 unknown box {}", bx.kind);
573 }
574
575 Ok(None)
576 }
577}
578
579impl<'a> Reader<'a> for &'a [u8] {
580 #[inline]
581 fn take(&mut self, size: usize) -> Result<impl Reader<'a> + '_, Error> {
582 if self.len() < size {
583 return Err(Error::InvalidData("no bytes left"));
584 }
585
586 let buff = &(*self)[0..size];
587 self.advance(size);
588
589 Ok(buff)
590 }
591
592 #[inline]
593 fn skip(&mut self, size: usize) {
594 Buf::advance(self, size)
595 }
596
597 #[inline]
598 fn remaining(&self) -> usize {
599 Buf::remaining(self)
600 }
601
602 fn peek_u32(&self) -> u32 {
603 BigEndian::read_u32(self.chunk())
604 }
605
606 #[inline]
607 fn get_u8(&mut self) -> u8 {
608 Buf::get_u8(self)
609 }
610
611 #[inline]
612 fn get_u16(&mut self) -> u16 {
613 Buf::get_u16(self)
614 }
615
616 #[inline]
617 fn get_u24(&mut self) -> u32 {
618 let val = BigEndian::read_u24(self.chunk());
619 self.skip(3);
620 val
621 }
622
623 #[inline]
624 fn get_u32(&mut self) -> u32 {
625 Buf::get_u32(self)
626 }
627
628 #[inline]
629 fn get_u48(&mut self) -> u64 {
630 let val = BigEndian::read_u48(self.chunk());
631 self.skip(6);
632 val
633 }
634
635 #[inline]
636 fn get_u64(&mut self) -> u64 {
637 Buf::get_u64(self)
638 }
639
640 #[inline]
641 fn get_i8(&mut self) -> i8 {
642 Buf::get_i8(self)
643 }
644
645 #[inline]
646 fn get_i16(&mut self) -> i16 {
647 Buf::get_i16(self)
648 }
649
650 #[inline]
651 fn get_i24(&mut self) -> i32 {
652 todo!()
653 }
654
655 #[inline]
656 fn get_i32(&mut self) -> i32 {
657 Buf::get_i32(self)
658 }
659
660 #[inline]
661 fn get_i48(&mut self) -> i64 {
662 todo!()
663 }
664
665 #[inline]
666 fn get_i64(&mut self) -> i64 {
667 Buf::get_i64(self)
668 }
669
670 #[inline]
671 fn copy_to_slice(&mut self, slice: &mut [u8]) -> Result<(), Error> {
672 if self.len() < slice.len() {
673 return Err(Error::InvalidData("expected more bytes"));
674 }
675
676 Buf::copy_to_slice(self, slice);
677
678 Ok(())
679 }
680
681 #[inline]
682 fn get_null_terminated_string(&mut self) -> String {
683 let rem = self.len();
684
685 if rem > 0 {
686 let size = self.iter().position(|&b| b == b'\0');
687
688 let (size, eat) = if let Some(size) = size {
689 (size, size + 1)
690 } else {
691 (rem, rem)
692 };
693
694 let val = String::from_utf8_lossy(&self[0..size]).to_string();
695 self.advance(eat);
696 val
697 } else {
698 String::new()
699 }
700 }
701
702 #[inline]
703 fn get_box(&mut self) -> Result<Option<BoxReader<'a, impl Reader<'a> + '_>>, Error> {
704 let mut offset = 0;
705 let Some(BoxHeader { kind, size }) = BoxHeader::read_sync(self, &mut offset)? else {
706 return Ok(None);
707 };
708
709 Ok(Some(BoxReader {
710 kind,
711 inner: Reader::take(self, (size - offset) as _)?,
712 m: PhantomData,
713 }))
714 }
715}
716
717pub trait BlockReader: Sized {
718 fn read_block<'a>(block: &mut impl Reader<'a>) -> Result<Self, Error>;
719 fn size_hint() -> usize;
720}
721
722pub trait WriteBox<T>: Sized {
723 fn write_box(&self, _: T) -> Result<u64, Error>;
724}
725
726#[derive(Debug, Clone, Copy)]
727pub struct BoxHeader {
728 pub kind: BoxType,
729 pub size: u64,
730}
731
732impl BoxHeader {
733 pub fn new(name: BoxType, size: u64) -> Self {
734 Self { kind: name, size }
735 }
736
737 pub fn read_sync<'a>(
738 reader: &mut impl Reader<'a>,
739 offset: &mut u64,
740 ) -> Result<Option<Self>, Error> {
741 if reader.remaining() < 8 {
742 return Ok(None);
743 }
744
745 let sz = reader.get_u32();
746 let typ = reader.get_u32();
747
748 *offset += 8;
749
750 let size = if sz == 1 {
752 if reader.remaining() < 8 {
753 return Err(Error::InvalidData("expected 8 bytes more"));
754 }
755
756 *offset += 8;
757
758 let largesize = reader.get_u64();
759 match largesize {
763 0 => 0,
764 1..=15 => return Err(Error::InvalidData("64-bit box size too small")),
765 16..=u64::MAX => largesize - 8,
766 }
767 } else {
768 sz as _
769 };
770
771 println!(
772 "{} box {} {}",
773 if sz == 1 { "big" } else { "small" },
774 BoxType::from(typ).as_str(),
775 size
776 );
777
778 Ok(Some(BoxHeader {
779 kind: BoxType::from(typ),
780 size,
781 }))
782 }
783
784 pub async fn read<R: AsyncRead + Unpin>(
786 reader: &mut R,
787 offset: &mut u64,
788 ) -> Result<Option<Self>, Error> {
789 let mut buf = [0u8; 8]; match reader.read_exact(&mut buf).await {
792 Ok(_) => (),
793 Err(err) => match err.kind() {
794 std::io::ErrorKind::UnexpectedEof => return Ok(None),
795 _ => return Err(err.into()),
796 },
797 }
798 *offset += 8;
799
800 let s = buf[0..4].try_into().unwrap();
802 let sz = u32::from_be_bytes(s);
803
804 let t = buf[4..8].try_into().unwrap();
806 let typ = u32::from_be_bytes(t);
807
808 let size = if sz == 1 {
810 match reader.read_exact(&mut buf).await {
811 Ok(_) => (),
812 Err(err) => match err.kind() {
813 std::io::ErrorKind::UnexpectedEof => return Ok(None),
814 _ => return Err(err.into()),
815 },
816 }
817
818 *offset += 8;
819 let largesize = u64::from_be_bytes(buf);
820
821 match largesize {
825 0 => 0,
826 1..=15 => return Err(Error::InvalidData("64-bit box size too small")),
827 16..=u64::MAX => largesize - 8,
828 }
829 } else {
830 sz as _
831 };
832
833 println!(
834 "{} box {} {}",
835 if sz == 1 { "big" } else { "small" },
836 BoxType::from(typ).as_str(),
837 size
838 );
839
840 Ok(Some(BoxHeader {
841 kind: BoxType::from(typ),
842 size,
843 }))
844 }
845
846 pub fn write<W: Write>(&self, writer: &mut W) -> Result<u64, Error> {
847 if self.size > u32::MAX as u64 {
848 writer.write_u32::<BigEndian>(1)?;
849 writer.write_u32::<BigEndian>(self.kind.into())?;
850 writer.write_u64::<BigEndian>(self.size)?;
851 Ok(16)
852 } else {
853 writer.write_u32::<BigEndian>(self.size as u32)?;
854 writer.write_u32::<BigEndian>(self.kind.into())?;
855 Ok(8)
856 }
857 }
858}
859
860#[inline]
861pub fn read_box_header_ext<'a, R: Reader<'a>>(reader: &mut R) -> (u8, u32) {
862 (reader.get_u8(), reader.get_u24())
863}
864
865pub fn write_box_header_ext<W: Write>(w: &mut W, v: u8, f: u32) -> Result<u64, Error> {
866 w.write_u8(v)?;
867 w.write_u24::<BigEndian>(f)?;
868 Ok(4)
869}
870
871pub fn write_zeros<W: Write>(writer: &mut W, size: u64) -> Result<(), Error> {
872 for _ in 0..size {
873 writer.write_u8(0)?;
874 }
875 Ok(())
876}
877
878mod value_u32 {
879 use crate::types::FixedPointU16;
880 use serde::{self, Serializer};
881
882 pub fn serialize<S>(fixed: &FixedPointU16, serializer: S) -> Result<S::Ok, S::Error>
883 where
884 S: Serializer,
885 {
886 serializer.serialize_u16(fixed.value())
887 }
888}
889
890mod value_i16 {
891 use crate::types::FixedPointI8;
892 use serde::{self, Serializer};
893
894 pub fn serialize<S>(fixed: &FixedPointI8, serializer: S) -> Result<S::Ok, S::Error>
895 where
896 S: Serializer,
897 {
898 serializer.serialize_i8(fixed.value())
899 }
900}
901
902mod value_u8 {
903 use crate::types::FixedPointU8;
904 use serde::{self, Serializer};
905
906 pub fn serialize<S>(fixed: &FixedPointU8, serializer: S) -> Result<S::Ok, S::Error>
907 where
908 S: Serializer,
909 {
910 serializer.serialize_u8(fixed.value())
911 }
912}
913
914#[cfg(test)]
915mod tests {
916 use super::*;
917
918 #[test]
919 fn test_fourcc() {
920 let ftyp_fcc = 0x66747970;
921 let ftyp_value = FourCC::from(ftyp_fcc);
922 assert_eq!(&ftyp_value.value[..], b"ftyp");
923 let ftyp_fcc2: u32 = ftyp_value.into();
924 assert_eq!(ftyp_fcc, ftyp_fcc2);
925 }
926
927 #[tokio::test]
928 async fn test_largesize_too_small() {
929 let error = BoxHeader::read(
930 &mut &[0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 7][..],
931 &mut 0,
932 )
933 .await;
934 assert!(matches!(error, Err(Error::InvalidData(_))));
935 }
936
937 #[tokio::test]
938 async fn test_zero_largesize() {
939 let error = BoxHeader::read(
940 &mut &[0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 8][..],
941 &mut 0,
942 )
943 .await;
944 assert!(matches!(error, Err(Error::InvalidData(_))));
945 }
946
947 #[tokio::test]
948 async fn test_nonzero_largesize_too_small() {
949 let error = BoxHeader::read(
950 &mut &[0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 15][..],
951 &mut 0,
952 )
953 .await;
954 assert!(matches!(error, Err(Error::InvalidData(_))));
955 }
956
957 #[tokio::test]
958 async fn test_valid_largesize() {
959 let header = BoxHeader::read(
960 &mut &[0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 16][..],
961 &mut 0,
962 )
963 .await;
964 assert!(matches!(header, Ok(Some(BoxHeader { size: 8, .. }))));
965 }
966}