use std::io::{self, Read, Write};
pub mod traits;
pub use traits::{BinaryRead, BinaryWrite};
pub fn read_u8<R: Read>(reader: &mut R) -> io::Result<u8> {
let mut buf = [0u8; 1];
reader.read_exact(&mut buf)?;
Ok(buf[0])
}
pub fn read_u16_be<R: Read>(reader: &mut R) -> io::Result<u16> {
let mut buf = [0u8; 2];
reader.read_exact(&mut buf)?;
Ok(u16::from_be_bytes(buf))
}
pub fn read_u24_be<R: Read>(reader: &mut R) -> io::Result<u32> {
let mut buf = [0u8; 3];
reader.read_exact(&mut buf)?;
Ok(u32::from_be_bytes([0, buf[0], buf[1], buf[2]]))
}
pub fn read_u32_be<R: Read>(reader: &mut R) -> io::Result<u32> {
let mut buf = [0u8; 4];
reader.read_exact(&mut buf)?;
Ok(u32::from_be_bytes(buf))
}
pub fn read_bytes<R: Read>(reader: &mut R, n: usize) -> io::Result<Vec<u8>> {
let mut buf = vec![0u8; n];
reader.read_exact(&mut buf)?;
Ok(buf)
}
pub fn write_u8<W: Write>(writer: &mut W, value: u8) -> io::Result<()> {
writer.write_all(&[value])
}
pub fn write_u16_be<W: Write>(writer: &mut W, value: u16) -> io::Result<()> {
writer.write_all(&value.to_be_bytes())
}
pub fn write_u24_be<W: Write>(writer: &mut W, value: u32) -> io::Result<()> {
if value > 0x00FF_FFFF {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"Value too large for u24",
));
}
let bytes = value.to_be_bytes();
writer.write_all(&bytes[1..4])
}
pub fn write_u32_be<W: Write>(writer: &mut W, value: u32) -> io::Result<()> {
writer.write_all(&value.to_be_bytes())
}
pub fn write_bytes<W: Write>(writer: &mut W, bytes: &[u8]) -> io::Result<()> {
writer.write_all(bytes)
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
#[test]
fn test_u8_roundtrip() {
let mut buf = Vec::new();
write_u8(&mut buf, 0x42).unwrap();
assert_eq!(buf, vec![0x42]);
let mut cursor = Cursor::new(buf);
assert_eq!(read_u8(&mut cursor).unwrap(), 0x42);
}
#[test]
fn test_u16_roundtrip() {
let mut buf = Vec::new();
write_u16_be(&mut buf, 0x1234).unwrap();
assert_eq!(buf, vec![0x12, 0x34]);
let mut cursor = Cursor::new(buf);
assert_eq!(read_u16_be(&mut cursor).unwrap(), 0x1234);
}
#[test]
fn test_u24_roundtrip() {
let mut buf = Vec::new();
write_u24_be(&mut buf, 0x12_3456).unwrap();
assert_eq!(buf, vec![0x12, 0x34, 0x56]);
let mut cursor = Cursor::new(buf);
assert_eq!(read_u24_be(&mut cursor).unwrap(), 0x12_3456);
}
#[test]
fn test_u24_overflow() {
let mut buf = Vec::new();
let result = write_u24_be(&mut buf, 0x01_000000);
assert!(result.is_err());
}
#[test]
fn test_u32_roundtrip() {
let mut buf = Vec::new();
write_u32_be(&mut buf, 0x12345678).unwrap();
assert_eq!(buf, vec![0x12, 0x34, 0x56, 0x78]);
let mut cursor = Cursor::new(buf);
assert_eq!(read_u32_be(&mut cursor).unwrap(), 0x12345678);
}
#[test]
fn test_bytes_roundtrip() {
let data = vec![0x01, 0x02, 0x03, 0x04, 0x05];
let mut buf = Vec::new();
write_bytes(&mut buf, &data).unwrap();
assert_eq!(buf, data);
let mut cursor = Cursor::new(buf);
assert_eq!(read_bytes(&mut cursor, 5).unwrap(), data);
}
}