1use crate::error::{Error, Result};
13
14macro_rules! read_fixed {
16 ($($(#[$attr:meta])* $name:ident -> $ty:ty, $conv:ident, $desc:literal, $size:literal;)*) => {$(
17 #[doc = concat!("Read a ", $desc, ".")]
18 #[doc = concat!("Returns [`Error::UnexpectedEof`] when fewer than ", $size, " bytes remain.")]
22 $(#[$attr])*
23 #[inline]
24 pub fn $name(&mut self) -> Result<$ty> {
25 self.read_array().map(<$ty>::$conv)
26 }
27 )*};
28}
29
30macro_rules! write_fixed {
32 ($($(#[$attr:meta])* $name:ident($ty:ty), $conv:ident, $desc:literal, $size:literal;)*) => {$(
33 #[doc = concat!("Write a ", $desc, ".")]
34 #[doc = concat!("Returns [`Error::BufferFull`] if fewer than ", $size, " bytes remain.")]
38 $(#[$attr])*
39 #[inline]
40 pub fn $name(&mut self, value: $ty) -> Result<()> {
41 self.write_bytes(&value.$conv())
42 }
43 )*};
44}
45
46#[derive(Debug, Clone)]
59pub struct ReadBuf<'a> {
60 bytes: &'a [u8],
61 pos: usize,
62}
63
64impl<'a> ReadBuf<'a> {
65 #[inline]
67 #[must_use]
68 pub const fn new(bytes: &'a [u8]) -> Self {
69 Self { bytes, pos: 0 }
70 }
71
72 #[inline]
77 #[must_use]
78 pub const fn position(&self) -> usize {
79 self.pos
80 }
81
82 #[inline]
84 #[must_use]
85 pub const fn remaining(&self) -> usize {
86 self.bytes.len() - self.pos
87 }
88
89 #[inline]
91 #[must_use]
92 pub const fn is_empty(&self) -> bool {
93 self.pos >= self.bytes.len()
94 }
95
96 #[inline]
98 #[must_use]
99 pub fn remaining_slice(&self) -> &'a [u8] {
100 &self.bytes[self.pos..]
101 }
102
103 #[inline]
109 pub fn peek(&self, n: usize) -> Result<&'a [u8]> {
110 let end = self.pos.checked_add(n).ok_or(Error::UnexpectedEof)?;
111 self.bytes.get(self.pos..end).ok_or(Error::UnexpectedEof)
112 }
113
114 #[inline]
130 pub fn peek_u8(&self) -> Result<u8> {
131 self.bytes
132 .get(self.pos)
133 .copied()
134 .ok_or(Error::UnexpectedEof)
135 }
136
137 #[inline]
143 pub fn read_bytes(&mut self, n: usize) -> Result<&'a [u8]> {
144 let slice = self.peek(n)?;
145 self.pos += n;
146 Ok(slice)
147 }
148
149 #[inline]
165 pub fn read_array<const N: usize>(&mut self) -> Result<[u8; N]> {
166 self.read_array_ref().copied()
167 }
168
169 #[inline]
186 pub fn read_array_ref<const N: usize>(&mut self) -> Result<&'a [u8; N]> {
187 let array = self
188 .remaining_slice()
189 .first_chunk::<N>()
190 .ok_or(Error::UnexpectedEof)?;
191 self.pos += N;
192 Ok(array)
193 }
194
195 #[inline]
219 pub fn split_to(&mut self, n: usize) -> Result<ReadBuf<'a>> {
220 self.read_bytes(n).map(ReadBuf::new)
221 }
222
223 #[inline]
229 pub fn advance(&mut self, n: usize) -> Result<()> {
230 self.read_bytes(n).map(|_| ())
231 }
232
233 #[inline]
238 pub(crate) fn consume(&mut self, n: usize) {
239 debug_assert!(n <= self.remaining());
240 self.pos += n;
241 }
242
243 #[inline]
249 pub fn read_u8(&mut self) -> Result<u8> {
250 let value = self.peek_u8()?;
251 self.pos += 1;
252 Ok(value)
253 }
254
255 #[inline]
261 pub fn read_i8(&mut self) -> Result<i8> {
262 self.read_u8().map(|b| b as i8)
263 }
264
265 read_fixed! {
266 read_u16_be -> u16, from_be_bytes, "big-endian `u16`", "2";
267 read_u16_le -> u16, from_le_bytes, "little-endian `u16`", "2";
268 read_u32_be -> u32, from_be_bytes, "big-endian `u32`", "4";
269 read_u32_le -> u32, from_le_bytes, "little-endian `u32`", "4";
270 read_u64_be -> u64, from_be_bytes, "big-endian `u64`", "8";
271 read_u64_le -> u64, from_le_bytes, "little-endian `u64`", "8";
272 read_u128_be -> u128, from_be_bytes, "big-endian `u128`", "16";
273 read_u128_le -> u128, from_le_bytes, "little-endian `u128`", "16";
274 read_i16_be -> i16, from_be_bytes, "big-endian `i16`", "2";
275 read_i16_le -> i16, from_le_bytes, "little-endian `i16`", "2";
276 read_i32_be -> i32, from_be_bytes, "big-endian `i32`", "4";
277 read_i32_le -> i32, from_le_bytes, "little-endian `i32`", "4";
278 read_i64_be -> i64, from_be_bytes, "big-endian `i64`", "8";
279 read_i64_le -> i64, from_le_bytes, "little-endian `i64`", "8";
280 read_i128_be -> i128, from_be_bytes, "big-endian `i128`", "16";
281 read_i128_le -> i128, from_le_bytes, "little-endian `i128`", "16";
282 read_f32_be -> f32, from_be_bytes, "big-endian IEEE 754 `f32`", "4";
283 read_f32_le -> f32, from_le_bytes, "little-endian IEEE 754 `f32`", "4";
284 read_f64_be -> f64, from_be_bytes, "big-endian IEEE 754 `f64`", "8";
285 read_f64_le -> f64, from_le_bytes, "little-endian IEEE 754 `f64`", "8";
286 }
287}
288
289#[derive(Debug)]
319pub struct WriteBuf<'a> {
320 bytes: &'a mut [u8],
321 pos: usize,
322}
323
324impl<'a> WriteBuf<'a> {
325 #[inline]
327 #[must_use]
328 pub fn new(bytes: &'a mut [u8]) -> Self {
329 Self { bytes, pos: 0 }
330 }
331
332 #[inline]
334 #[must_use]
335 pub fn capacity(&self) -> usize {
336 self.bytes.len()
337 }
338
339 #[inline]
341 #[must_use]
342 pub fn position(&self) -> usize {
343 self.pos
344 }
345
346 #[inline]
348 #[must_use]
349 pub fn remaining(&self) -> usize {
350 self.bytes.len() - self.pos
351 }
352
353 #[inline]
355 #[must_use]
356 pub fn written(&self) -> &[u8] {
357 &self.bytes[..self.pos]
358 }
359
360 #[inline]
366 pub fn write_bytes(&mut self, src: &[u8]) -> Result<()> {
367 let end = self.pos.checked_add(src.len()).ok_or(Error::BufferFull)?;
368 let dst = self.bytes.get_mut(self.pos..end).ok_or(Error::BufferFull)?;
369 dst.copy_from_slice(src);
370 self.pos = end;
371 Ok(())
372 }
373
374 #[inline]
380 pub fn write_u8(&mut self, value: u8) -> Result<()> {
381 let slot = self.bytes.get_mut(self.pos).ok_or(Error::BufferFull)?;
382 *slot = value;
383 self.pos += 1;
384 Ok(())
385 }
386
387 #[inline]
393 pub fn write_i8(&mut self, value: i8) -> Result<()> {
394 self.write_u8(value as u8)
395 }
396
397 write_fixed! {
398 write_u16_be(u16), to_be_bytes, "big-endian `u16`", "2";
399 write_u16_le(u16), to_le_bytes, "little-endian `u16`", "2";
400 write_u32_be(u32), to_be_bytes, "big-endian `u32`", "4";
401 write_u32_le(u32), to_le_bytes, "little-endian `u32`", "4";
402 write_u64_be(u64), to_be_bytes, "big-endian `u64`", "8";
403 write_u64_le(u64), to_le_bytes, "little-endian `u64`", "8";
404 write_u128_be(u128), to_be_bytes, "big-endian `u128`", "16";
405 write_u128_le(u128), to_le_bytes, "little-endian `u128`", "16";
406 write_i16_be(i16), to_be_bytes, "big-endian `i16`", "2";
407 write_i16_le(i16), to_le_bytes, "little-endian `i16`", "2";
408 write_i32_be(i32), to_be_bytes, "big-endian `i32`", "4";
409 write_i32_le(i32), to_le_bytes, "little-endian `i32`", "4";
410 write_i64_be(i64), to_be_bytes, "big-endian `i64`", "8";
411 write_i64_le(i64), to_le_bytes, "little-endian `i64`", "8";
412 write_i128_be(i128), to_be_bytes, "big-endian `i128`", "16";
413 write_i128_le(i128), to_le_bytes, "little-endian `i128`", "16";
414 write_f32_be(f32), to_be_bytes, "big-endian IEEE 754 `f32`", "4";
415 write_f32_le(f32), to_le_bytes, "little-endian IEEE 754 `f32`", "4";
416 write_f64_be(f64), to_be_bytes, "big-endian IEEE 754 `f64`", "8";
417 write_f64_le(f64), to_le_bytes, "little-endian IEEE 754 `f64`", "8";
418 }
419
420 #[inline]
425 pub(crate) fn spare_mut(&mut self) -> &mut [u8] {
426 &mut self.bytes[self.pos..]
427 }
428
429 #[inline]
431 pub(crate) fn commit(&mut self, n: usize) {
432 debug_assert!(n <= self.remaining());
433 self.pos += n;
434 }
435
436 #[inline]
439 pub(crate) fn rewind(&mut self, pos: usize) {
440 debug_assert!(pos <= self.pos);
441 self.pos = pos;
442 }
443
444 #[inline]
446 #[must_use]
447 pub fn into_written(self) -> &'a mut [u8] {
448 &mut self.bytes[..self.pos]
449 }
450}
451
452#[cfg(test)]
453mod tests {
454 use super::*;
455
456 #[test]
457 fn read_buf_round_trip() {
458 let data = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
459 let mut buf = ReadBuf::new(&data);
460 assert_eq!(buf.read_u8().unwrap(), 0x01);
461 assert_eq!(buf.read_u16_be().unwrap(), 0x0203);
462 assert_eq!(buf.read_u32_be().unwrap(), 0x04050607);
463 assert_eq!(buf.remaining(), 1);
464 assert_eq!(buf.read_u8().unwrap(), 0x08);
465 assert!(buf.is_empty());
466 }
467
468 #[test]
469 fn read_buf_eof() {
470 let mut buf = ReadBuf::new(&[0x01]);
471 assert_eq!(buf.read_u8().unwrap(), 0x01);
472 assert_eq!(buf.read_u8(), Err(Error::UnexpectedEof));
473 assert_eq!(buf.read_i8(), Err(Error::UnexpectedEof));
474 assert_eq!(buf.peek_u8(), Err(Error::UnexpectedEof));
475 }
476
477 #[test]
478 fn read_buf_peek_does_not_advance() {
479 let buf = ReadBuf::new(&[0xAA, 0xBB]);
480 assert_eq!(buf.peek(2).unwrap(), &[0xAA, 0xBB]);
481 assert_eq!(buf.position(), 0);
482 assert_eq!(buf.peek(3), Err(Error::UnexpectedEof));
483 assert_eq!(buf.peek(usize::MAX), Err(Error::UnexpectedEof));
484 }
485
486 #[test]
487 fn every_fixed_width_read_in_both_orders() {
488 let data: Vec<u8> = (1..=16).collect();
489 let mut be = ReadBuf::new(&data);
490 assert_eq!(
491 be.read_u128_be().unwrap(),
492 u128::from_be_bytes(data[..].try_into().unwrap())
493 );
494 let mut le = ReadBuf::new(&data);
495 assert_eq!(
496 le.read_u128_le().unwrap(),
497 u128::from_le_bytes(data[..].try_into().unwrap())
498 );
499
500 let mut r = ReadBuf::new(&data);
501 assert_eq!(r.read_u16_le().unwrap(), 0x0201);
502 assert_eq!(r.read_u32_le().unwrap(), 0x0605_0403);
503 assert_eq!(r.read_u64_le().unwrap(), 0x0E0D_0C0B_0A09_0807);
504 assert_eq!(r.read_u16_be().unwrap(), 0x0F10);
505
506 let mut r = ReadBuf::new(&data);
507 assert_eq!(r.read_u64_be().unwrap(), 0x0102_0304_0506_0708);
508
509 let neg = [0xFFu8; 16];
510 let mut r = ReadBuf::new(&neg);
511 assert_eq!(r.read_i8().unwrap(), -1);
512 assert_eq!(r.read_i16_be().unwrap(), -1);
513 assert_eq!(r.read_i16_le().unwrap(), -1);
514 assert_eq!(r.read_i32_be().unwrap(), -1);
515 assert_eq!(r.read_i32_le().unwrap(), -1);
516 assert_eq!(r.remaining(), 3);
517 let mut r = ReadBuf::new(&neg);
518 assert_eq!(r.read_i64_be().unwrap(), -1);
519 assert_eq!(r.read_i64_le().unwrap(), -1);
520 let mut r = ReadBuf::new(&neg);
521 assert_eq!(r.read_i128_be().unwrap(), -1);
522 let mut r = ReadBuf::new(&neg);
523 assert_eq!(r.read_i128_le().unwrap(), -1);
524 }
525
526 #[test]
527 fn float_round_trip() {
528 let mut storage = [0u8; 24];
529 let mut w = WriteBuf::new(&mut storage);
530 w.write_f32_be(1.5).unwrap();
531 w.write_f32_le(-2.25).unwrap();
532 w.write_f64_be(core::f64::consts::PI).unwrap();
533 w.write_f64_le(f64::MIN_POSITIVE).unwrap();
534 assert_eq!(&storage[..4], &1.5f32.to_be_bytes());
535 let mut r = ReadBuf::new(&storage);
536 assert_eq!(r.read_f32_be().unwrap(), 1.5);
537 assert_eq!(r.read_f32_le().unwrap(), -2.25);
538 assert_eq!(r.read_f64_be().unwrap(), core::f64::consts::PI);
539 assert_eq!(r.read_f64_le().unwrap(), f64::MIN_POSITIVE);
540 assert!(r.is_empty());
541 }
542
543 #[test]
544 fn short_fixed_reads_are_atomic() {
545 let mut r = ReadBuf::new(&[1, 2, 3]);
546 assert_eq!(r.read_u32_be(), Err(Error::UnexpectedEof));
547 assert_eq!(r.read_array::<4>(), Err(Error::UnexpectedEof));
548 assert_eq!(r.read_array_ref::<4>(), Err(Error::UnexpectedEof));
549 assert_eq!(
550 r.split_to(4).map(|b| b.remaining()),
551 Err(Error::UnexpectedEof)
552 );
553 assert_eq!(r.advance(4), Err(Error::UnexpectedEof));
554 assert_eq!(r.advance(usize::MAX), Err(Error::UnexpectedEof));
555 assert_eq!(r.position(), 0);
556 }
557
558 #[test]
559 fn arrays_split_and_advance() {
560 let data = [1u8, 2, 3, 4, 5, 6];
561 let mut r = ReadBuf::new(&data);
562 assert_eq!(r.read_array::<2>().unwrap(), [1, 2]);
563 assert_eq!(r.read_array_ref::<1>().unwrap(), &[3]);
564 r.advance(1).unwrap();
565 assert_eq!(r.position(), 4);
566 assert_eq!(r.remaining_slice(), &[5, 6]);
567 let sub = r.split_to(2).unwrap();
568 assert_eq!(sub.remaining_slice(), &[5, 6]);
569 assert!(r.is_empty());
570 assert_eq!(r.read_array::<0>().unwrap(), [0u8; 0]);
571 }
572
573 #[test]
574 fn write_buf_round_trip() {
575 let mut storage = [0u8; 8];
576 let mut buf = WriteBuf::new(&mut storage);
577 buf.write_u8(0x01).unwrap();
578 buf.write_u16_be(0x0203).unwrap();
579 buf.write_u32_le(0x07060504).unwrap();
580 buf.write_u8(0x08).unwrap();
581 assert_eq!(&storage, &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
582 }
583
584 #[test]
585 fn every_fixed_width_write() {
586 let mut storage = [0u8; 64];
587 let mut w = WriteBuf::new(&mut storage);
588 w.write_i8(-2).unwrap();
589 w.write_u16_le(0x0102).unwrap();
590 w.write_i16_be(-2).unwrap();
591 w.write_i16_le(-2).unwrap();
592 w.write_u32_be(0x0102_0304).unwrap();
593 w.write_i32_be(-2).unwrap();
594 w.write_i32_le(-2).unwrap();
595 w.write_u64_be(1).unwrap();
596 w.write_u64_le(1).unwrap();
597 w.write_i64_be(-2).unwrap();
598 w.write_i64_le(-2).unwrap();
599 assert_eq!(w.position(), 1 + 2 * 3 + 4 * 3 + 8 * 4);
600 let n = w.position();
601 let mut r = ReadBuf::new(&storage[..n]);
602 assert_eq!(r.read_i8().unwrap(), -2);
603 assert_eq!(r.read_u16_le().unwrap(), 0x0102);
604 assert_eq!(r.read_i16_be().unwrap(), -2);
605 assert_eq!(r.read_i16_le().unwrap(), -2);
606 assert_eq!(r.read_u32_be().unwrap(), 0x0102_0304);
607 assert_eq!(r.read_i32_be().unwrap(), -2);
608 assert_eq!(r.read_i32_le().unwrap(), -2);
609 assert_eq!(r.read_u64_be().unwrap(), 1);
610 assert_eq!(r.read_u64_le().unwrap(), 1);
611 assert_eq!(r.read_i64_be().unwrap(), -2);
612 assert_eq!(r.read_i64_le().unwrap(), -2);
613
614 let mut storage = [0u8; 64];
615 let mut w = WriteBuf::new(&mut storage);
616 w.write_u128_be(7).unwrap();
617 w.write_u128_le(7).unwrap();
618 w.write_i128_be(-7).unwrap();
619 w.write_i128_le(-7).unwrap();
620 let mut r = ReadBuf::new(&storage);
621 assert_eq!(r.read_u128_be().unwrap(), 7);
622 assert_eq!(r.read_u128_le().unwrap(), 7);
623 assert_eq!(r.read_i128_be().unwrap(), -7);
624 assert_eq!(r.read_i128_le().unwrap(), -7);
625 }
626
627 #[test]
628 fn write_buf_full() {
629 let mut storage = [0u8; 2];
630 let mut buf = WriteBuf::new(&mut storage);
631 buf.write_u16_be(0x1234).unwrap();
632 assert_eq!(buf.write_u8(0), Err(Error::BufferFull));
633 assert_eq!(buf.write_i8(0), Err(Error::BufferFull));
634 assert_eq!(buf.write_bytes(&[]), Ok(()));
635 assert_eq!(buf.write_bytes(&[0]), Err(Error::BufferFull));
636 }
637
638 #[test]
639 fn write_buf_accessors() {
640 let mut storage = [0u8; 4];
641 let mut buf = WriteBuf::new(&mut storage);
642 assert_eq!(buf.capacity(), 4);
643 assert_eq!(buf.remaining(), 4);
644 buf.write_bytes(&[9, 8, 7, 6]).unwrap();
645 assert_eq!(buf.remaining(), 0);
646 assert_eq!(buf.write_u32_be(0), Err(Error::BufferFull));
647 assert_eq!(buf.position(), 4);
648 let written = buf.into_written();
649 written[0] = 1;
650 assert_eq!(storage, [1, 8, 7, 6]);
651 }
652}