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 header = match Header::decode_maybe(buf)? {
48 Some(header) => header,
49 None => return Ok(None),
50 };
51
52 let size = header.size.unwrap_or(buf.remaining());
53 if size > buf.remaining() {
54 return Ok(None);
55 }
56
57 let body = &mut buf.slice(size);
58
59 let atom = match Self::decode_body(body) {
60 Ok(atom) => atom,
61 Err(Error::OutOfBounds) => return Err(Error::OverDecode(T::KIND)),
62 Err(Error::ShortRead) => return Err(Error::UnderDecode(T::KIND)),
63 Err(err) => return Err(err),
64 };
65
66 if body.has_remaining() {
67 return Err(Error::UnderDecode(T::KIND));
68 }
69
70 buf.advance(size);
71
72 Ok(Some(atom))
73 }
74}
75
76impl<T: Atom> ReadFrom for T {
77 fn read_from<R: Read>(r: &mut R) -> Result<Self> {
78 <Option<T> as ReadFrom>::read_from(r)?.ok_or(Error::MissingBox(T::KIND))
79 }
80}
81
82impl<T: Atom> ReadFrom for Option<T> {
83 fn read_from<R: Read>(r: &mut R) -> Result<Self> {
84 let header = match <Option<Header> as ReadFrom>::read_from(r)? {
85 Some(header) => header,
86 None => return Ok(None),
87 };
88
89 let body = &mut header.read_body(r)?;
90
91 let atom = match T::decode_body(body) {
92 Ok(atom) => atom,
93 Err(Error::OutOfBounds) => return Err(Error::OverDecode(T::KIND)),
94 Err(Error::ShortRead) => return Err(Error::UnderDecode(T::KIND)),
95 Err(err) => return Err(err),
96 };
97
98 if body.has_remaining() {
99 return Err(Error::UnderDecode(T::KIND));
100 }
101
102 Ok(Some(atom))
103 }
104}
105
106impl<T: Atom> ReadUntil for T {
107 fn read_until<R: Read>(r: &mut R) -> Result<Self> {
108 <Option<T> as ReadUntil>::read_until(r)?.ok_or(Error::MissingBox(T::KIND))
109 }
110}
111
112impl<T: Atom> ReadUntil for Option<T> {
113 fn read_until<R: Read>(r: &mut R) -> Result<Self> {
114 while let Some(header) = <Option<Header> as ReadFrom>::read_from(r)? {
115 if header.kind == T::KIND {
116 let body = &mut header.read_body(r)?;
117 return Ok(Some(T::decode_atom(&header, body)?));
118 }
119 }
120
121 Ok(None)
122 }
123}
124
125impl<T: Atom> DecodeAtom for T {
126 fn decode_atom<B: Buf>(header: &Header, buf: &mut B) -> Result<T> {
127 if header.kind != T::KIND {
128 return Err(Error::UnexpectedBox(header.kind));
129 }
130
131 let size = header.size.unwrap_or(buf.remaining());
132 if size > buf.remaining() {
133 return Err(Error::OutOfBounds);
134 }
135
136 let body = &mut buf.slice(size);
137
138 let atom = match T::decode_body(body) {
139 Ok(atom) => atom,
140 Err(Error::OutOfBounds) => return Err(Error::OverDecode(T::KIND)),
141 Err(Error::ShortRead) => return Err(Error::UnderDecode(T::KIND)),
142 Err(err) => return Err(err),
143 };
144
145 if body.has_remaining() {
146 return Err(Error::UnderDecode(T::KIND));
147 }
148
149 buf.advance(size);
150
151 Ok(atom)
152 }
153}
154
155impl<T: Atom> ReadAtom for T {
156 fn read_atom<R: Read>(header: &Header, r: &mut R) -> Result<Self> {
157 if header.kind != T::KIND {
158 return Err(Error::UnexpectedBox(header.kind));
159 }
160
161 let body = &mut header.read_body(r)?;
162 Self::decode_atom(header, body)
163 }
164}
165
166macro_rules! nested {
176 (required: [$($required:ident),*$(,)?], optional: [$($optional:ident),*$(,)?], multiple: [$($multiple:ident),*$(,)?],) => {
177 paste::paste! {
178 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
179 $( let mut [<$required:lower>] = None;)*
180 $( let mut [<$optional:lower>] = None;)*
181 $( let mut [<$multiple:lower>] = Vec::new();)*
182
183 while let Some(atom) = Any::decode_maybe(buf)? {
184 match atom {
185 $(Any::$required(atom) => {
186 if [<$required:lower>].is_some() {
187 return Err(Error::DuplicateBox($required::KIND));
188 }
189 [<$required:lower>] = Some(atom);
190 },)*
191 $(Any::$optional(atom) => {
192 if [<$optional:lower>].is_some() {
193 return Err(Error::DuplicateBox($optional::KIND));
194 }
195 [<$optional:lower>] = Some(atom);
196 },)*
197 $(Any::$multiple(atom) => {
198 [<$multiple:lower>].push(atom.into());
199 },)*
200 Any::Skip(atom) => tracing::debug!(size = atom.zeroed.size, "skipping skip box"),
201 Any::Free(atom) => tracing::debug!(size = atom.zeroed.size, "skipping free box"),
202 unknown => Self::decode_unknown(&unknown)?,
203 }
204 }
205
206 Ok(Self {
207 $([<$required:lower>]: [<$required:lower>].ok_or(Error::MissingBox($required::KIND))? ,)*
208 $([<$optional:lower>],)*
209 $([<$multiple:lower>],)*
210 })
211 }
212
213 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
214 $( self.[<$required:lower>].encode(buf)?; )*
215 $( self.[<$optional:lower>].encode(buf)?; )*
216 $( self.[<$multiple:lower>].iter().map(|x| x.encode(buf)).collect::<Result<()>>()?; )*
217
218 Ok(())
219 }
220 }
221 };
222}
223
224pub(crate) use nested;