Skip to content

Instantly share code, notes, and snippets.

@fkohlgrueber
Created December 14, 2021 08:46
Show Gist options
  • Save fkohlgrueber/fc696a1ce8414c316d675f5ca6d33c69 to your computer and use it in GitHub Desktop.
Save fkohlgrueber/fc696a1ce8414c316d675f5ca6d33c69 to your computer and use it in GitHub Desktop.
Using const generics to make the Read trait and parsing more ergonomic
use std::io::{self, Read};
pub trait MyRead: Read {
#[inline(always)]
fn read_to_buf<const N: usize>(&mut self) -> io::Result<[u8; N]> {
let mut buf = [0; N];
self.read_exact(&mut buf)?;
Ok(buf)
}
}
impl<T> MyRead for T where T: Read {}
fn main() -> io::Result<()> {
// create a reader for some example data
let data: Vec<_> = (0..100u8).collect();
let mut reader = io::Cursor::new(data);
// traditional reading into a buffer:
let mut buf1 = [0u8; 5];
reader.read_exact(&mut buf1)?;
// using read_to_buf, you can do this instead:
let buf2: [u8; 5] = reader.read_to_buf()?;
let buf3 = reader.read_to_buf::<5>()?;
assert_eq!(buf1, [0, 1, 2, 3, 4]);
assert_eq!(buf2, [5, 6, 7, 8, 9]);
assert_eq!(buf3, [10, 11, 12, 13, 14]);
// the difference is even larger when parsing integers:
// using read:
let mut buf = [0u8; 2];
reader.read_exact(&mut buf)?;
let num1 = u16::from_le_bytes(buf);
// using read_to_buf:
let num2 = u16::from_le_bytes(reader.read_to_buf()?);
let num3 = reader.read_to_buf().map(u16::from_le_bytes)?;
assert_eq!(num1, (16 << 8) + 15);
assert_eq!(num2, (18 << 8) + 17);
assert_eq!(num3, (20 << 8) + 19);
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment