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