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
13impl<T: Atom> Encode for T {
14 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
15 let start = buf.len();
16
17 0u32.encode(buf)?;
19 Self::KIND.encode(buf)?;
20 self.encode_body(buf)?;
21
22 let size: u32 = (buf.len() - start)
25 .try_into()
26 .map_err(|_| Error::TooLarge(T::KIND))?;
27
28 buf.set_slice(start, &size.to_be_bytes());
29
30 Ok(())
31 }
32}
33
34impl<T: Atom> Decode for T {
35 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
36 Self::decode_maybe(buf)?.ok_or(Error::OutOfBounds)
37 }
38}
39
40impl<T: Atom> DecodeMaybe for T {
41 fn decode_maybe<B: Buf>(buf: &mut B) -> Result<Option<Self>> {
42 let header = match Header::decode_maybe(buf)? {
43 Some(header) => header,
44 None => return Ok(None),
45 };
46
47 let size = header.size.unwrap_or(buf.remaining());
48 if size > buf.remaining() {
49 return Ok(None);
50 }
51
52 let body = &mut buf.slice(size);
53
54 let atom = match Self::decode_body(body) {
55 Ok(atom) => atom,
56 Err(Error::OutOfBounds) => return Err(Error::OverDecode(T::KIND)),
57 Err(Error::ShortRead) => return Err(Error::UnderDecode(T::KIND)),
58 Err(err) => return Err(err),
59 };
60
61 if body.has_remaining() {
62 return Err(Error::UnderDecode(T::KIND));
63 }
64
65 buf.advance(size);
66
67 Ok(Some(atom))
68 }
69}
70
71impl<T: Atom> ReadFrom for T {
72 fn read_from<R: Read>(r: &mut R) -> Result<Self> {
73 <Option<T> as ReadFrom>::read_from(r)?.ok_or(Error::MissingBox(T::KIND))
74 }
75}
76
77impl<T: Atom> ReadFrom for Option<T> {
78 fn read_from<R: Read>(r: &mut R) -> Result<Self> {
79 let header = match <Option<Header> as ReadFrom>::read_from(r)? {
80 Some(header) => header,
81 None => return Ok(None),
82 };
83
84 let body = &mut header.read_body(r)?;
85
86 let atom = match T::decode_body(body) {
87 Ok(atom) => atom,
88 Err(Error::OutOfBounds) => return Err(Error::OverDecode(T::KIND)),
89 Err(Error::ShortRead) => return Err(Error::UnderDecode(T::KIND)),
90 Err(err) => return Err(err),
91 };
92
93 if body.has_remaining() {
94 return Err(Error::UnderDecode(T::KIND));
95 }
96
97 Ok(Some(atom))
98 }
99}
100
101impl<T: Atom> ReadUntil for T {
102 fn read_until<R: Read>(r: &mut R) -> Result<Self> {
103 <Option<T> as ReadUntil>::read_until(r)?.ok_or(Error::MissingBox(T::KIND))
104 }
105}
106
107impl<T: Atom> ReadUntil for Option<T> {
108 fn read_until<R: Read>(r: &mut R) -> Result<Self> {
109 while let Some(header) = <Option<Header> as ReadFrom>::read_from(r)? {
110 if header.kind == T::KIND {
111 let body = &mut header.read_body(r)?;
112 return Ok(Some(T::decode_atom(&header, body)?));
113 }
114 }
115
116 Ok(None)
117 }
118}
119
120impl<T: Atom> DecodeAtom for T {
121 fn decode_atom<B: Buf>(header: &Header, buf: &mut B) -> Result<T> {
122 if header.kind != T::KIND {
123 return Err(Error::UnexpectedBox(header.kind));
124 }
125
126 let size = header.size.unwrap_or(buf.remaining());
127 if size > buf.remaining() {
128 return Err(Error::OutOfBounds);
129 }
130
131 let body = &mut buf.slice(size);
132
133 let atom = match T::decode_body(body) {
134 Ok(atom) => atom,
135 Err(Error::OutOfBounds) => return Err(Error::OverDecode(T::KIND)),
136 Err(Error::ShortRead) => return Err(Error::UnderDecode(T::KIND)),
137 Err(err) => return Err(err),
138 };
139
140 if body.has_remaining() {
141 return Err(Error::UnderDecode(T::KIND));
142 }
143
144 buf.advance(size);
145
146 Ok(atom)
147 }
148}
149
150impl<T: Atom> ReadAtom for T {
151 fn read_atom<R: Read>(header: &Header, r: &mut R) -> Result<Self> {
152 if header.kind != T::KIND {
153 return Err(Error::UnexpectedBox(header.kind));
154 }
155
156 let body = &mut header.read_body(r)?;
157 Self::decode_atom(header, body)
158 }
159}
160
161macro_rules! nested {
171 (required: [$($required:ident),*$(,)?], optional: [$($optional:ident),*$(,)?], multiple: [$($multiple:ident),*$(,)?],) => {
172 paste::paste! {
173 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
174 $( let mut [<$required:lower>] = None;)*
175 $( let mut [<$optional:lower>] = None;)*
176 $( let mut [<$multiple:lower>] = Vec::new();)*
177
178 while let Some(atom) = Any::decode_maybe(buf)? {
179 match atom {
180 $(Any::$required(atom) => {
181 if [<$required:lower>].is_some() {
182 return Err(Error::DuplicateBox($required::KIND));
183 }
184 [<$required:lower>] = Some(atom);
185 },)*
186 $(Any::$optional(atom) => {
187 if [<$optional:lower>].is_some() {
188 return Err(Error::DuplicateBox($optional::KIND));
189 }
190 [<$optional:lower>] = Some(atom);
191 },)*
192 $(Any::$multiple(atom) => {
193 [<$multiple:lower>].push(atom);
194 },)*
195 Any::Unknown(kind, _) => {
196 tracing::warn!("unknown box: {:?}", kind);
197 },
198 _ => return Err(Error::UnexpectedBox(atom.kind())),
199 }
200 }
201
202 Ok(Self {
203 $([<$required:lower>]: [<$required:lower>].ok_or(Error::MissingBox($required::KIND))? ,)*
204 $([<$optional:lower>],)*
205 $([<$multiple:lower>],)*
206 })
207 }
208
209 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
210 $( self.[<$required:lower>].encode(buf)?; )*
211 $( self.[<$optional:lower>].encode(buf)?; )*
212 $( self.[<$multiple:lower>].encode(buf)?; )*
213
214 Ok(())
215 }
216 }
217 };
218}
219
220pub(crate) use nested;