#![deny(unsafe_code)]
use std::io::{self, Read, Write};
use std::mem::size_of;
pub trait ReadFrom : Sized {
type Error;
fn read_from<R: Read>(input: R) -> Result<Self, Self::Error>;
}
pub trait WriteTo {
type Error;
fn write_to<W: Write>(&self, output: W) -> Result<usize, Self::Error>;
}
impl ReadFrom for u8 {
type Error = io::Error;
#[inline]
fn read_from<R: Read>(mut inp: R) -> Result<Self, Self::Error> {
let mut buf = [0; 1];
inp.read_exact(&mut buf)?;
let [byte] = buf;
Ok(byte)
}
}
impl ReadFrom for i8 {
type Error = io::Error;
#[inline]
fn read_from<R: Read>(mut inp: R) -> Result<Self, Self::Error> {
let mut buf = [0; 1];
inp.read_exact(&mut buf)?;
let [byte] = buf;
Ok(byte as _)
}
}
impl WriteTo for u8 {
type Error = io::Error;
#[inline]
fn write_to<W: Write>(&self, mut out: W) -> Result<usize, Self::Error> {
out.write_all(&[*self]).and(Ok(1))
}
}
impl WriteTo for i8 {
type Error = io::Error;
#[inline]
fn write_to<W: Write>(&self, mut out: W) -> Result<usize, Self::Error> {
out.write_all(&[*self as u8]).and(Ok(1))
}
}
macro_rules! impl_for_array {
($($len:literal)*) => {
$(
impl ReadFrom for [u8; $len] {
type Error = io::Error;
fn read_from<R: Read>(mut inp: R) -> Result<Self, Self::Error> {
let mut buf = [0; $len];
inp.read_exact(&mut buf).and(Ok(buf))
}
}
impl WriteTo for [u8; $len] {
type Error = io::Error;
fn write_to<W: Write>(&self, mut out: W) -> Result<usize, Self::Error> {
out.write_all(self).and(Ok($len))
}
}
)*
};
}
impl_for_array!(
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
64 128 256 512 1024 2048 4096 8192
50 100 250 500 1000 2500 5000 10000
);
#[repr(transparent)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LittleEndian<T>(pub T);
#[repr(transparent)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct BigEndian<T>(pub T);
#[repr(transparent)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NativeEndian<T>(pub T);
pub type NetworkEndian<T> = BigEndian<T>;
macro_rules! impl_endian_traits {
($endian:ident $from_bytes:ident $to_bytes:ident; $($ty:ident)*) => {
$(
impl ReadFrom for $endian<$ty> {
type Error = io::Error;
fn read_from<R: Read>(mut inp: R) -> Result<Self, Self::Error> {
let mut buf = [0; size_of::<$ty>()];
inp.read_exact(&mut buf)?;
Ok(Self(<$ty>::$from_bytes(buf)))
}
}
)*
$(
impl WriteTo for $endian<$ty> {
type Error = io::Error;
fn write_to<W: Write>(&self, mut out: W)
-> Result<usize, Self::Error>
{
out.write_all(&self.0.$to_bytes()).and(Ok(size_of::<$ty>()))
}
}
)*
};
($($ty:ident)*) => {
impl_endian_traits!(LittleEndian from_le_bytes to_le_bytes; $($ty)*);
impl_endian_traits!(BigEndian from_be_bytes to_be_bytes; $($ty)*);
impl_endian_traits!(NativeEndian from_ne_bytes to_ne_bytes; $($ty)*);
};
}
impl_endian_traits!(
u8 u16 u32 u64 u128 usize
i8 i16 i32 i64 i128 isize
f32 f64
);