1use std::ffi;
2
3use crate::*;
4
5pub trait Decode: Sized {
7 fn decode<B: Buf>(buf: &mut B) -> Result<Self>;
9
10 fn decode_exact<B: Buf>(buf: &mut B, size: usize) -> Result<Self> {
12 if buf.remaining() < size {
13 return Err(Error::OutOfBounds);
14 }
15
16 let mut inner = buf.slice(size);
17 let res = Self::decode(&mut inner)?;
18
19 if inner.has_remaining() {
20 return Err(Error::ShortRead);
21 }
22
23 buf.advance(size);
24
25 Ok(res)
26 }
27}
28
29pub trait DecodeMaybe: Sized {
31 fn decode_maybe<B: Buf>(buf: &mut B) -> Result<Option<Self>>;
32}
33
34pub trait DecodeAtom: Sized {
36 fn decode_atom<B: Buf>(header: &Header, buf: &mut B) -> Result<Self>;
37}
38
39pub trait Encode {
46 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()>;
47
48 #[cfg(test)]
49 fn assert_encode_decode(&self)
50 where
51 Self: std::fmt::Debug + PartialEq + Decode,
52 {
53 let mut buf = Vec::new();
54 Self::encode(self, &mut buf).unwrap();
55
56 let mut cursor = std::io::Cursor::new(&buf);
57 let decoded = Self::decode(&mut cursor).unwrap();
58
59 assert_eq!(self, &decoded, "different decoded result");
60 }
61}
62
63impl Decode for u8 {
64 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
65 Ok(Self::from_be_bytes(<[u8; 1]>::decode(buf)?))
66 }
67}
68
69impl Decode for i8 {
70 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
71 Ok(Self::from_be_bytes(<[u8; 1]>::decode(buf)?))
72 }
73}
74
75impl Decode for u16 {
76 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
77 Ok(Self::from_be_bytes(<[u8; 2]>::decode(buf)?))
78 }
79}
80
81impl Decode for i16 {
82 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
83 Ok(Self::from_be_bytes(<[u8; 2]>::decode(buf)?))
84 }
85}
86
87impl Decode for u32 {
88 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
89 Ok(Self::from_be_bytes(<[u8; 4]>::decode(buf)?))
90 }
91}
92
93impl Decode for i32 {
94 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
95 Ok(Self::from_be_bytes(<[u8; 4]>::decode(buf)?))
96 }
97}
98
99impl Decode for u64 {
100 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
101 Ok(Self::from_be_bytes(<[u8; 8]>::decode(buf)?))
102 }
103}
104
105impl Decode for i64 {
106 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
107 Ok(Self::from_be_bytes(<[u8; 8]>::decode(buf)?))
108 }
109}
110
111impl<const N: usize> Decode for [u8; N] {
112 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
113 if buf.remaining() < N {
114 return Err(Error::OutOfBounds);
115 }
116
117 let mut v = [0u8; N];
118 v.copy_from_slice(buf.slice(N));
119 buf.advance(N);
120
121 Ok(v)
122 }
123}
124
125impl<T: Decode> Decode for Vec<T> {
126 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
127 let mut vec = Vec::new();
128 while buf.has_remaining() {
129 let item = T::decode(buf)?;
130 vec.push(item);
131 }
132
133 Ok(vec)
134 }
135}
136
137impl Decode for String {
138 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
139 let mut bytes = Vec::new();
140 while buf.has_remaining() {
141 let byte = u8::decode(buf)?;
142 if byte == 0 {
143 break;
144 }
145
146 bytes.push(byte);
147 }
148
149 let str = ffi::CString::new(bytes).map_err(|err| Error::InvalidString(err.to_string()))?;
150 str.into_string()
151 .map_err(|err| Error::InvalidString(err.to_string()))
152 }
153}
154
155impl Encode for u8 {
156 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
157 self.to_be_bytes().encode(buf)
158 }
159}
160
161impl Encode for i8 {
162 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
163 self.to_be_bytes().encode(buf)
164 }
165}
166
167impl Encode for i16 {
168 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
169 self.to_be_bytes().encode(buf)
170 }
171}
172
173impl Encode for u16 {
174 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
175 self.to_be_bytes().encode(buf)
176 }
177}
178
179impl Encode for u32 {
180 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
181 self.to_be_bytes().encode(buf)
182 }
183}
184
185impl Encode for i32 {
186 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
187 self.to_be_bytes().encode(buf)
188 }
189}
190
191impl Encode for u64 {
192 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
193 self.to_be_bytes().encode(buf)
194 }
195}
196
197impl Encode for i64 {
198 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
199 self.to_be_bytes().encode(buf)
200 }
201}
202
203impl<const N: usize> Encode for [u8; N] {
204 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
205 buf.append_slice(self);
206 Ok(())
207 }
208}
209
210impl<T: Encode> Encode for &[T] {
211 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
212 for item in self.iter() {
213 item.encode(buf)?;
214 }
215
216 Ok(())
217 }
218}
219
220impl<T: Encode> Encode for Option<T> {
221 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
222 match self {
223 Some(v) => v.encode(buf),
224 None => Ok(()),
225 }
226 }
227}
228
229impl Encode for &str {
230 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
231 self.as_bytes().encode(buf)?;
232 0u8.encode(buf)?;
233 Ok(())
234 }
235}
236
237impl<T: Encode> Encode for Vec<T> {
238 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
239 for item in self.iter() {
240 item.encode(buf)?;
241 }
242
243 Ok(())
244 }
245}
246
247pub(crate) fn decode_length_prefixed_utf8_string<T: Decode + Into<usize>>(
249 buf: &mut impl Buf,
250) -> Result<String> {
251 let len = T::decode(buf)?;
252 decode_utf8_string_with_length(buf, len.into())
253}
254
255pub(crate) fn decode_utf8_string(buf: &mut impl Buf) -> Result<String> {
257 decode_utf8_string_with_length(buf, buf.remaining())
258}
259
260pub(crate) fn decode_utf8_string_with_length(buf: &mut impl Buf, len: usize) -> Result<String> {
262 if len > buf.remaining() {
263 return Err(Error::OutOfBounds);
264 }
265
266 let text = String::from_utf8(buf.slice(len).to_vec())
267 .map_err(|err| Error::InvalidString(err.to_string()))?;
268
269 buf.advance(len);
270 Ok(text)
271}
272
273pub(crate) fn encode_length_prefixed_string<T: Encode + TryFrom<usize>>(
276 buf: &mut impl BufMut,
277 text: &str,
278 kind: FourCC,
279) -> Result<()> {
280 let len: T = text.len().try_into().map_err(|_| Error::TooLarge(kind))?;
281 len.encode(buf)?;
282 buf.append_slice(text.as_bytes());
283 Ok(())
284}
285
286pub(crate) fn decode_length_prefixed_bom_string<T: Decode + Into<usize>>(
289 buf: &mut impl Buf,
290) -> Result<String> {
291 let len = T::decode(buf)?;
292 decode_bom_string_with_length(buf, len.into())
293}
294
295pub(crate) fn decode_bom_string_with_length(buf: &mut impl Buf, len: usize) -> Result<String> {
298 if len > buf.remaining() {
299 return Err(Error::OutOfBounds);
300 }
301
302 let bytes = buf.slice(len);
303 let text = match bytes {
304 [0xFE, 0xFF, rest @ ..] => decode_utf16_units(rest, u16::from_be_bytes),
305 [0xFF, 0xFE, rest @ ..] => decode_utf16_units(rest, u16::from_le_bytes),
306 _ => String::from_utf8(bytes.to_vec()).map_err(|err| err.to_string()),
307 }
308 .map_err(Error::InvalidString)?;
309
310 buf.advance(len);
311 Ok(text)
312}
313
314fn decode_utf16_units(
315 bytes: &[u8],
316 from_bytes: fn([u8; 2]) -> u16,
317) -> std::result::Result<String, String> {
318 let (pairs, rest) = bytes.as_chunks::<2>();
319
320 if !rest.is_empty() {
321 return Err("UTF-16 payload has an odd byte length".to_string());
322 }
323
324 let units: Vec<u16> = pairs.iter().cloned().map(from_bytes).collect();
325 String::from_utf16(&units).map_err(|err| err.to_string())
326}
327
328#[cfg(test)]
329mod string_helper_tests {
330 use super::*;
331
332 #[test]
333 fn test_length_prefixed_string_roundtrip() {
334 let mut buf = Vec::new();
335 encode_length_prefixed_string::<u8>(&mut buf, "héllo", FourCC::new(b"test")).unwrap();
336 assert_eq!(buf[0] as usize, "héllo".len());
337
338 let mut slice = buf.as_slice();
339 assert_eq!(
340 decode_length_prefixed_utf8_string::<u8>(&mut slice).unwrap(),
341 "héllo"
342 );
343 assert!(slice.is_empty());
344 }
345
346 #[test]
347 fn test_length_prefixed_string_errors() {
348 let too_long = "a".repeat(256);
349 let err =
350 encode_length_prefixed_string::<u8>(&mut Vec::new(), &too_long, FourCC::new(b"test"));
351 assert!(matches!(err, Err(Error::TooLarge(_))));
352
353 let err = decode_length_prefixed_utf8_string::<u8>(&mut [5u8, b'a'].as_slice());
355 assert!(matches!(err, Err(Error::OutOfBounds)));
356 }
357
358 #[test]
359 fn test_bom_string() {
360 let mut utf8 = b"Hi".as_slice();
361 assert_eq!(decode_bom_string_with_length(&mut utf8, 2).unwrap(), "Hi");
362 assert!(utf8.is_empty());
363
364 let be = [0xFE, 0xFF, 0, b'H', 0, b'i'];
365 assert_eq!(
366 decode_bom_string_with_length(&mut be.as_slice(), 6).unwrap(),
367 "Hi"
368 );
369
370 let le = [0xFF, 0xFE, b'H', 0, b'i', 0];
371 assert_eq!(
372 decode_bom_string_with_length(&mut le.as_slice(), 6).unwrap(),
373 "Hi"
374 );
375 }
376
377 #[test]
378 fn test_bom_string_errors() {
379 let err = decode_bom_string_with_length(&mut b"Hi".as_slice(), 3);
381 assert!(matches!(err, Err(Error::OutOfBounds)));
382
383 let odd = [0xFE, 0xFF, 0, b'H', 0];
385 let mut slice = odd.as_slice();
386 assert!(matches!(
387 decode_bom_string_with_length(&mut slice, 5),
388 Err(Error::InvalidString(_))
389 ));
390 assert_eq!(slice.len(), 5);
391 }
392}