1use std::io::{Cursor, Read};
2
3use crate::*;
4
5#[derive(Debug, Clone, Copy)]
7pub struct Header {
8 pub kind: FourCC,
10
11 pub size: Option<usize>,
14}
15
16impl Encode for Header {
17 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
18 match self.size.map(|size| size + 8) {
19 Some(size) if size > u32::MAX as usize => {
20 1u32.encode(buf)?;
21 self.kind.encode(buf)?;
22
23 ((size + 8) as u64).encode(buf)
25 }
26 Some(size) => {
27 (size as u32).encode(buf)?;
28 self.kind.encode(buf)
29 }
30 None => {
31 0u32.encode(buf)?;
32 self.kind.encode(buf)
33 }
34 }
35 }
36}
37
38impl Decode for Header {
39 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
40 let size = u32::decode(buf)?;
41 let kind = FourCC::decode(buf)?;
42
43 let size = match size {
44 0 => None,
45 1 => {
46 let size = u64::decode(buf)?;
48 Some(size.checked_sub(16).ok_or(Error::InvalidSize)? as usize)
49 }
50 _ => Some(size.checked_sub(8).ok_or(Error::InvalidSize)? as usize),
51 };
52
53 Ok(Self { kind, size })
54 }
55}
56
57impl DecodeMaybe for Header {
58 fn decode_maybe<B: Buf>(buf: &mut B) -> Result<Option<Self>> {
59 if buf.remaining() < 8 {
60 return Ok(None);
61 }
62
63 let size = u32::from_be_bytes(buf.slice(4).try_into().unwrap());
64 if size == 1 && buf.remaining() < 16 {
65 return Ok(None);
66 }
67
68 Ok(Some(Self::decode(buf)?))
69 }
70}
71
72impl ReadFrom for Header {
73 fn read_from<R: Read>(r: &mut R) -> Result<Self> {
74 <Option<Header> as ReadFrom>::read_from(r)?.ok_or(Error::UnexpectedEof)
75 }
76}
77
78impl ReadFrom for Option<Header> {
79 fn read_from<R: Read>(r: &mut R) -> Result<Self> {
80 let mut buf = [0u8; 8];
81 let n = r.read(&mut buf)?;
82 if n == 0 {
83 return Ok(None);
84 }
85
86 r.read_exact(&mut buf[n..])?;
87
88 let size = u32::from_be_bytes(buf[0..4].try_into().unwrap());
89 let kind = u32::from_be_bytes(buf[4..8].try_into().unwrap()).into();
90
91 let size = match size {
92 0 => None,
93 1 => {
94 r.read_exact(&mut buf)?;
96 let size = u64::from_be_bytes(buf);
97 let size = size.checked_sub(16).ok_or(Error::InvalidSize)?;
98
99 Some(size as usize)
100 }
101 _ => Some(size.checked_sub(8).ok_or(Error::InvalidSize)? as usize),
102 };
103
104 Ok(Some(Header { kind, size }))
105 }
106}
107
108impl Header {
110 pub(crate) fn read_body<R: Read>(&self, r: &mut R) -> Result<Cursor<Vec<u8>>> {
111 let cap = self.size.unwrap_or(0).min(4096);
117 let mut buf = Vec::with_capacity(cap);
118
119 match self.size {
120 Some(size) => {
121 let n = std::io::copy(&mut r.take(size as _), &mut buf)? as _;
122 if size != n {
123 return Err(Error::OutOfBounds);
124 }
125 }
126 None => {
127 std::io::copy(r, &mut buf)?;
128 }
129 };
130
131 Ok(Cursor::new(buf))
132 }
133
134 #[cfg(feature = "tokio")]
135 pub(crate) async fn read_body_tokio<R: ::tokio::io::AsyncRead + Unpin>(
136 &self,
137 r: &mut R,
138 ) -> Result<Cursor<Vec<u8>>> {
139 use ::tokio::io::AsyncReadExt;
140
141 let cap = self.size.unwrap_or(0).min(4096);
147 let mut buf = Vec::with_capacity(cap);
148
149 match self.size {
150 Some(size) => {
151 let n = ::tokio::io::copy(&mut r.take(size as _), &mut buf).await? as _;
152 if size != n {
153 return Err(Error::OutOfBounds);
154 }
155 }
156 None => {
157 ::tokio::io::copy(r, &mut buf).await?;
158 }
159 };
160
161 Ok(Cursor::new(buf))
162 }
163}