use std::{
fmt,
io::{self, Cursor, Read, Write},
mem::size_of,
};
use koibumi_net::Port;
pub use crate::error::TooLongError;
pub trait WriteTo {
fn write_to(&self, w: &mut dyn Write) -> io::Result<()>;
}
pub trait ReadFrom {
fn read_from(r: &mut dyn Read) -> io::Result<Self>
where
Self: Sized;
}
impl WriteTo for u8 {
fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
let bytes = [*self];
w.write_all(&bytes)
}
}
impl ReadFrom for u8 {
fn read_from(r: &mut dyn Read) -> io::Result<Self>
where
Self: Sized,
{
let mut buf = [0; 1];
r.read_exact(&mut buf)?;
Ok(buf[0])
}
}
impl WriteTo for u16 {
fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
w.write_all(&self.to_be_bytes())
}
}
impl ReadFrom for u16 {
fn read_from(r: &mut dyn Read) -> io::Result<Self>
where
Self: Sized,
{
let mut buf = [0; 2];
r.read_exact(&mut buf)?;
Ok(Self::from_be_bytes(buf))
}
}
impl WriteTo for u32 {
fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
w.write_all(&self.to_be_bytes())
}
}
impl ReadFrom for u32 {
fn read_from(r: &mut dyn Read) -> io::Result<Self>
where
Self: Sized,
{
let mut buf = [0; 4];
r.read_exact(&mut buf)?;
Ok(Self::from_be_bytes(buf))
}
}
impl WriteTo for u64 {
fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
w.write_all(&self.to_be_bytes())
}
}
impl ReadFrom for u64 {
fn read_from(r: &mut dyn Read) -> io::Result<Self>
where
Self: Sized,
{
let mut buf = [0; 8];
r.read_exact(&mut buf)?;
Ok(Self::from_be_bytes(buf))
}
}
impl WriteTo for [u8] {
fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
w.write_all(self)
}
}
macro_rules! io_array {
($len:expr) => {
impl ReadFrom for [u8; $len] {
fn read_from(r: &mut dyn Read) -> io::Result<Self>
where
Self: Sized,
{
let mut buf = [0; $len];
r.read_exact(&mut buf)?;
Ok(buf)
}
}
};
}
io_array!(4);
io_array!(6);
io_array!(10);
io_array!(12);
io_array!(16);
io_array!(18);
io_array!(20);
io_array!(32);
impl WriteTo for Vec<u8> {
fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
w.write_all(self)
}
}
impl WriteTo for Port {
fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
self.as_u16().write_to(w)
}
}
impl ReadFrom for Port {
fn read_from(r: &mut dyn Read) -> io::Result<Self>
where
Self: Sized,
{
Ok(Self::new(u16::read_from(r)?))
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct TrailingBytesError(usize);
impl fmt::Display for TrailingBytesError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "found trailing {} bytes", self.0)
}
}
impl std::error::Error for TrailingBytesError {}
impl TrailingBytesError {
pub fn new(trailing_len: usize) -> Self {
Self(trailing_len)
}
pub fn trailing_len(&self) -> usize {
self.0
}
}
pub trait SizedReadFrom {
fn sized_read_from(r: &mut dyn Read, len: usize) -> io::Result<Self>
where
Self: Sized;
}
impl SizedReadFrom for Vec<u8> {
fn sized_read_from(r: &mut dyn Read, len: usize) -> io::Result<Self>
where
Self: Sized,
{
let mut r = r.take(len as u64);
let mut bytes = Vec::with_capacity(len);
r.read_to_end(&mut bytes)?;
Ok(bytes)
}
}
pub trait LimitedReadFrom {
fn limited_read_from(r: &mut dyn Read, max_len: usize) -> io::Result<Self>
where
Self: Sized;
}
pub trait ReadFromExact {
fn read_from_exact(bytes: impl AsRef<[u8]>) -> io::Result<Self>
where
Self: Sized;
}
impl<T> ReadFromExact for T
where
T: ReadFrom,
{
fn read_from_exact(bytes: impl AsRef<[u8]>) -> io::Result<Self>
where
Self: Sized,
{
let bytes = bytes.as_ref();
let mut cur = Cursor::new(bytes);
let v = Self::read_from(&mut cur)?;
if cur.position() != bytes.len() as u64 {
return Err(io::Error::new(
io::ErrorKind::Other,
TrailingBytesError(bytes.len() - cur.position() as usize),
));
}
Ok(v)
}
}
pub trait SizedReadFromExact {
fn sized_read_from_exact(bytes: impl AsRef<[u8]>) -> io::Result<Self>
where
Self: Sized;
}
impl<T> SizedReadFromExact for T
where
T: SizedReadFrom,
{
fn sized_read_from_exact(bytes: impl AsRef<[u8]>) -> io::Result<Self>
where
Self: Sized,
{
let bytes = bytes.as_ref();
let mut cur = Cursor::new(bytes);
Self::sized_read_from(&mut cur, bytes.len())
}
}
pub trait LenBm {
fn len_bm(&self) -> usize;
}
impl LenBm for u32 {
fn len_bm(&self) -> usize {
size_of::<u32>()
}
}
impl LenBm for u64 {
fn len_bm(&self) -> usize {
size_of::<u64>()
}
}