1use core::mem::size_of;
5
6use crate::error::{Incomplete, InvalidWidth};
7
8pub fn take(buf: &[u8], n: usize) -> Result<(&[u8], &[u8]), Incomplete> {
13 if buf.len() < n {
14 Err(Incomplete {
15 needed: n,
16 available: buf.len(),
17 })
18 } else {
19 Ok(buf.split_at(n))
20 }
21}
22
23pub fn read_u8(buf: &[u8]) -> Result<(u8, &[u8]), Incomplete> {
28 let (b, rest) = take(buf, 1)?;
29 Ok((b[0], rest))
30}
31
32pub fn read_u16_be(buf: &[u8]) -> Result<(u16, &[u8]), Incomplete> {
37 let (b, rest) = take(buf, 2)?;
38 Ok((u16::from_be_bytes([b[0], b[1]]), rest))
39}
40
41pub fn read_u32_be(buf: &[u8]) -> Result<(u32, &[u8]), Incomplete> {
46 let (b, rest) = take(buf, 4)?;
47 Ok((u32::from_be_bytes([b[0], b[1], b[2], b[3]]), rest))
48}
49
50pub fn read_u64_be(buf: &[u8]) -> Result<(u64, &[u8]), Incomplete> {
55 let (b, rest) = take(buf, 8)?;
56 Ok((
57 u64::from_be_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]),
58 rest,
59 ))
60}
61
62pub fn read_u128_be(buf: &[u8]) -> Result<(u128, &[u8]), Incomplete> {
67 let (arr, rest) = read_array::<16>(buf)?;
68 Ok((u128::from_be_bytes(arr), rest))
69}
70
71pub fn read_array<const N: usize>(buf: &[u8]) -> Result<([u8; N], &[u8]), Incomplete> {
76 let (b, rest) = take(buf, N)?;
77 let mut arr = [0u8; N];
78 arr.copy_from_slice(b);
79 Ok((arr, rest))
80}
81
82#[derive(Clone, Copy, Debug, Eq, PartialEq)]
85pub enum ReadUintError {
86 Incomplete(Incomplete),
88 InvalidWidth(InvalidWidth),
90}
91
92impl From<Incomplete> for ReadUintError {
93 fn from(e: Incomplete) -> Self {
94 ReadUintError::Incomplete(e)
95 }
96}
97impl From<InvalidWidth> for ReadUintError {
98 fn from(e: InvalidWidth) -> Self {
99 ReadUintError::InvalidWidth(e)
100 }
101}
102impl core::fmt::Display for ReadUintError {
103 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
104 match self {
105 ReadUintError::Incomplete(e) => e.fmt(f),
106 ReadUintError::InvalidWidth(e) => e.fmt(f),
107 }
108 }
109}
110impl core::error::Error for ReadUintError {}
111
112pub fn read_be_uint(buf: &[u8], n: usize) -> Result<(u128, &[u8]), ReadUintError> {
123 if n > 16 {
124 return Err(InvalidWidth { max: 16, got: n }.into());
125 }
126 let (b, rest) = take(buf, n)?;
127 let mut acc: u128 = 0;
128 for &byte in b {
129 acc = (acc << 8) | u128::from(byte);
130 }
131 Ok((acc, rest))
132}
133
134mod sealed {
135 pub trait Sealed {}
136}
137
138pub trait BeUint: sealed::Sealed + Sized {
141 const BYTES: usize;
143 #[doc(hidden)]
144 fn from_u128(v: u128) -> Self;
145}
146
147macro_rules! impl_be_uint {
148 ($($t:ty),*) => {$(
149 impl sealed::Sealed for $t {}
150 impl BeUint for $t {
151 const BYTES: usize = size_of::<$t>();
152 #[allow(clippy::cast_possible_truncation, clippy::cast_lossless)]
153 fn from_u128(v: u128) -> Self {
154 v as $t
156 }
157 }
158 )*};
159}
160impl_be_uint!(u8, u16, u32, u64, u128);
161
162pub fn read_be_uint_into<T: BeUint>(buf: &[u8], n: usize) -> Result<(T, &[u8]), ReadUintError> {
170 if n > T::BYTES {
171 return Err(InvalidWidth {
172 max: T::BYTES,
173 got: n,
174 }
175 .into());
176 }
177 let (v, rest) = read_be_uint(buf, n)?;
178 Ok((T::from_u128(v), rest))
179}
180
181#[inline]
189pub fn ensure_len(buf: &[u8], needed: usize) -> Result<(), Incomplete> {
190 if buf.len() < needed {
191 Err(Incomplete {
192 needed,
193 available: buf.len(),
194 })
195 } else {
196 Ok(())
197 }
198}
199
200#[must_use]
210pub fn read_optional_array<const N: usize>(buf: &[u8]) -> (Option<[u8; N]>, &[u8]) {
211 match read_array::<N>(buf) {
212 Ok((arr, rest)) => (Some(arr), rest),
213 Err(_) => (None, buf),
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220
221 #[test]
222 fn take_splits_and_returns_remainder() {
223 let (head, tail) = take(&[1, 2, 3, 4], 2).unwrap();
224 assert_eq!(head, &[1, 2]);
225 assert_eq!(tail, &[3, 4]);
226 }
227
228 #[test]
229 fn take_past_end_is_incomplete() {
230 let buf = [1, 2, 3];
231 assert_eq!(
232 take(&buf, 4),
233 Err(Incomplete {
234 needed: 4,
235 available: 3
236 })
237 );
238 }
239
240 #[test]
241 fn read_u16_be_reads_big_endian_and_remainder() {
242 let (v, rest) = read_u16_be(&[0x12, 0x34, 0x56]).unwrap();
243 assert_eq!(v, 0x1234);
244 assert_eq!(rest, &[0x56]);
245 }
246
247 #[test]
248 fn read_u32_be_exact_leaves_empty_remainder() {
249 let (v, rest) = read_u32_be(&[0xDE, 0xAD, 0xBE, 0xEF]).unwrap();
250 assert_eq!(v, 0xDEAD_BEEF);
251 assert!(rest.is_empty());
252 }
253
254 #[test]
255 fn read_helpers_one_byte_short_are_incomplete() {
256 assert_eq!(
257 read_u8(&[]),
258 Err(Incomplete {
259 needed: 1,
260 available: 0
261 })
262 );
263 assert_eq!(
264 read_u16_be(&[0]),
265 Err(Incomplete {
266 needed: 2,
267 available: 1
268 })
269 );
270 assert_eq!(
271 read_u32_be(&[0; 3]),
272 Err(Incomplete {
273 needed: 4,
274 available: 3
275 })
276 );
277 assert_eq!(
278 read_u64_be(&[0; 7]),
279 Err(Incomplete {
280 needed: 8,
281 available: 7
282 })
283 );
284 }
285
286 #[test]
287 fn read_array_reads_fixed_width() {
288 let (arr, rest) = read_array::<3>(&[1, 2, 3, 4]).unwrap();
289 assert_eq!(arr, [1, 2, 3]);
290 assert_eq!(rest, &[4]);
291 assert_eq!(
292 read_array::<3>(&[1, 2]),
293 Err(Incomplete {
294 needed: 3,
295 available: 2
296 })
297 );
298 }
299
300 #[test]
301 fn read_be_uint_reads_low_n_bytes() {
302 let (v, rest) = read_be_uint(&[0x01, 0x02, 0x03], 2).unwrap();
303 assert_eq!(v, 0x0102);
304 assert_eq!(rest, &[0x03]);
305 assert_eq!(
306 read_be_uint(&[0x00], 2),
307 Err(ReadUintError::Incomplete(Incomplete {
308 needed: 2,
309 available: 1
310 }))
311 );
312 }
313
314 #[test]
315 fn read_be_uint_hostile_width_is_data_error_not_panic() {
316 let buf = [0u8; 300];
318 assert_eq!(
319 read_be_uint(&buf, 255),
320 Err(ReadUintError::InvalidWidth(InvalidWidth {
321 max: 16,
322 got: 255
323 }))
324 );
325 assert_eq!(
326 read_be_uint(&buf, 17),
327 Err(ReadUintError::InvalidWidth(InvalidWidth {
328 max: 16,
329 got: 17
330 }))
331 );
332 }
333
334 #[test]
335 fn read_be_uint_zero_width_reads_nothing() {
336 let buf = [0xAA, 0xBB];
338 let (v, rest) = read_be_uint(&buf, 0).unwrap();
339 assert_eq!(v, 0);
340 assert_eq!(rest, &buf);
341 }
342
343 #[test]
344 fn read_be_uint_into_returns_target_type() {
345 let buf = [0x01, 0x02, 0x03, 0xFF];
347 let (v, rest) = read_be_uint_into::<u32>(&buf, 3).unwrap();
348 assert_eq!(v, 0x0001_0203_u32);
349 assert_eq!(rest, &[0xFF]);
350 }
351
352 #[test]
353 fn read_be_uint_into_rejects_width_wider_than_target() {
354 let buf = [0u8; 8];
356 assert_eq!(
357 read_be_uint_into::<u32>(&buf, 5),
358 Err(ReadUintError::InvalidWidth(InvalidWidth { max: 4, got: 5 }))
359 );
360 }
361
362 #[test]
363 fn read_be_uint_into_full_width_roundtrips() {
364 let buf = 0xDEAD_BEEF_u32.to_be_bytes();
365 let (v, rest) = read_be_uint_into::<u32>(&buf, 4).unwrap();
366 assert_eq!(v, 0xDEAD_BEEF);
367 assert!(rest.is_empty());
368 let (b, _) = read_be_uint_into::<u8>(&buf, 1).unwrap();
369 assert_eq!(b, 0xDE);
370 }
371
372 #[test]
373 fn read_u128_be_reads_full_width() {
374 let v = 0x0102_0304_0506_0708_090A_0B0C_0D0E_0F10_u128;
375 let bytes = v.to_be_bytes();
376 let mut buf = [0u8; 17];
377 buf[..16].copy_from_slice(&bytes);
378 buf[16] = 0xFF;
379 let (got, rest) = read_u128_be(&buf).unwrap();
380 assert_eq!(got, v);
381 assert_eq!(rest, &[0xFF]);
382 assert_eq!(
383 read_u128_be(&[0u8; 15]),
384 Err(Incomplete {
385 needed: 16,
386 available: 15
387 })
388 );
389 }
390
391 #[test]
392 fn ensure_len_passes_and_fails_with_counts() {
393 assert_eq!(ensure_len(&[1, 2, 3], 3), Ok(()));
394 assert_eq!(ensure_len(&[1, 2, 3], 2), Ok(()));
395 assert_eq!(
396 ensure_len(&[1, 2, 3], 4),
397 Err(Incomplete {
398 needed: 4,
399 available: 3
400 })
401 );
402 }
403
404 #[test]
405 fn read_optional_array_present_and_absent() {
406 let (arr, rest) = read_optional_array::<4>(&[1, 2, 3, 4, 5]);
408 assert_eq!(arr, Some([1, 2, 3, 4]));
409 assert_eq!(rest, &[5]);
410
411 let (arr, rest) = read_optional_array::<4>(&[]);
412 assert_eq!(arr, None);
413 assert!(rest.is_empty());
414
415 let (arr, rest) = read_optional_array::<4>(&[1, 2]);
418 assert_eq!(arr, None);
419 assert_eq!(rest, &[1, 2]);
420 }
421}