1use std::io::Read;
2
3use crate::*;
4
5pub trait Atom: Sized {
7 const KIND: FourCC;
8
9 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self>;
10 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()>;
11
12 fn decode_unknown(atom: &crate::Any) -> Result<()> {
14 crate::decode_unknown(atom, Self::KIND)
15 }
16}
17
18impl<T: Atom> Encode for T {
19 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
20 let start = buf.len();
21
22 0u32.encode(buf)?;
24 Self::KIND.encode(buf)?;
25 self.encode_body(buf)?;
26
27 let size: u32 = (buf.len() - start)
30 .try_into()
31 .map_err(|_| Error::TooLarge(T::KIND))?;
32
33 buf.set_slice(start, &size.to_be_bytes());
34
35 Ok(())
36 }
37}
38
39impl<T: Atom> Decode for T {
40 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
41 Self::decode_maybe(buf)?.ok_or(Error::OutOfBounds)
42 }
43}
44
45impl<T: Atom> DecodeMaybe for T {
46 fn decode_maybe<B: Buf>(buf: &mut B) -> Result<Option<Self>> {
47 let remaining = buf.remaining();
50 let mut peek = buf.slice(remaining);
51 let header = match Header::decode_maybe(&mut peek)? {
52 Some(header) => header,
53 None => return Ok(None),
54 };
55
56 let size = header.size.unwrap_or(peek.remaining());
57 if size > peek.remaining() {
58 return Ok(None);
59 }
60
61 buf.advance(remaining - peek.remaining());
62 let body = &mut buf.slice(size);
63
64 let atom = match Self::decode_body(body) {
65 Ok(atom) => atom,
66 Err(Error::OutOfBounds) => return Err(Error::OverDecode(T::KIND)),
67 Err(Error::ShortRead) => return Err(Error::UnderDecode(T::KIND)),
68 Err(err) => return Err(err),
69 };
70
71 if body.has_remaining() {
72 return Err(Error::UnderDecode(T::KIND));
73 }
74
75 buf.advance(size);
76
77 Ok(Some(atom))
78 }
79}
80
81impl<T: Atom> ReadFrom for T {
82 fn read_from<R: Read + ?Sized>(r: &mut R) -> Result<Self> {
83 <Option<T> as ReadFrom>::read_from(r)?.ok_or(Error::MissingBox(T::KIND))
84 }
85}
86
87impl<T: Atom> ReadFrom for Option<T> {
88 fn read_from<R: Read + ?Sized>(r: &mut R) -> Result<Self> {
89 let header = match <Option<Header> as ReadFrom>::read_from(r)? {
90 Some(header) => header,
91 None => return Ok(None),
92 };
93
94 let body = &mut header.read_body(r)?;
95
96 let atom = match T::decode_body(body) {
97 Ok(atom) => atom,
98 Err(Error::OutOfBounds) => return Err(Error::OverDecode(T::KIND)),
99 Err(Error::ShortRead) => return Err(Error::UnderDecode(T::KIND)),
100 Err(err) => return Err(err),
101 };
102
103 if body.has_remaining() {
104 return Err(Error::UnderDecode(T::KIND));
105 }
106
107 Ok(Some(atom))
108 }
109}
110
111impl<T: Atom> ReadUntil for T {
112 fn read_until<R: Read + ?Sized>(r: &mut R) -> Result<Self> {
113 <Option<T> as ReadUntil>::read_until(r)?.ok_or(Error::MissingBox(T::KIND))
114 }
115}
116
117impl<T: Atom> ReadUntil for Option<T> {
118 fn read_until<R: Read + ?Sized>(r: &mut R) -> Result<Self> {
119 while let Some(header) = <Option<Header> as ReadFrom>::read_from(r)? {
120 if header.kind == T::KIND {
121 let body = &mut header.read_body(r)?;
122 return Ok(Some(T::decode_atom(&header, body)?));
123 }
124 }
125
126 Ok(None)
127 }
128}
129
130impl<T: Atom> DecodeAtom for T {
131 fn decode_atom<B: Buf>(header: &Header, buf: &mut B) -> Result<T> {
132 if header.kind != T::KIND {
133 return Err(Error::UnexpectedBox(header.kind));
134 }
135
136 let size = header.size.unwrap_or(buf.remaining());
137 if size > buf.remaining() {
138 return Err(Error::OutOfBounds);
139 }
140
141 let body = &mut buf.slice(size);
142
143 let atom = match T::decode_body(body) {
144 Ok(atom) => atom,
145 Err(Error::OutOfBounds) => return Err(Error::OverDecode(T::KIND)),
146 Err(Error::ShortRead) => return Err(Error::UnderDecode(T::KIND)),
147 Err(err) => return Err(err),
148 };
149
150 if body.has_remaining() {
151 return Err(Error::UnderDecode(T::KIND));
152 }
153
154 buf.advance(size);
155
156 Ok(atom)
157 }
158}
159
160impl<T: Atom> ReadAtom for T {
161 fn read_atom<R: Read + ?Sized>(header: &Header, r: &mut R) -> Result<Self> {
162 if header.kind != T::KIND {
163 return Err(Error::UnexpectedBox(header.kind));
164 }
165
166 let body = &mut header.read_body(r)?;
167 Self::decode_atom(header, body)
168 }
169}
170
171macro_rules! nested {
181 (required: [$($required:ident),*$(,)?], optional: [$($optional:ident),*$(,)?], multiple: [$($multiple:ident),*$(,)?],) => {
182 pastey::paste! {
183 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
184 $( let mut [<$required:lower>] = None;)*
185 $( let mut [<$optional:lower>] = None;)*
186 $( let mut [<$multiple:lower>] = Vec::new();)*
187
188 while let Some(atom) = Any::decode_maybe(buf)? {
189 match atom {
190 $(Any::$required(atom) => {
191 if [<$required:lower>].is_some() {
192 return Err(Error::DuplicateBox($required::KIND));
193 }
194 [<$required:lower>] = Some(atom);
195 },)*
196 $(Any::$optional(atom) => {
197 if [<$optional:lower>].is_some() {
198 return Err(Error::DuplicateBox($optional::KIND));
199 }
200 [<$optional:lower>] = Some(atom);
201 },)*
202 $(Any::$multiple(atom) => {
203 [<$multiple:lower>].push(atom.into());
204 },)*
205 Any::Skip(atom) => tracing::debug!(size = atom.zeroed.size, "skipping skip box"),
206 Any::Free(atom) => tracing::debug!(size = atom.zeroed.size, "skipping free box"),
207 unknown => Self::decode_unknown(&unknown)?,
208 }
209 }
210 skip_trailing_padding(buf);
213
214 Ok(Self {
215 $([<$required:lower>]: [<$required:lower>].ok_or(Error::MissingBox($required::KIND))? ,)*
216 $([<$optional:lower>],)*
217 $([<$multiple:lower>],)*
218 })
219 }
220
221 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
222 $( self.[<$required:lower>].encode(buf)?; )*
223 $( self.[<$optional:lower>].encode(buf)?; )*
224 $( self.[<$multiple:lower>].iter().map(|x| x.encode(buf)).collect::<Result<()>>()?; )*
225
226 Ok(())
227 }
228 }
229 };
230}
231
232pub(crate) use nested;