use core::convert::TryInto; pub trait ByteOrder { fn read_u16(buf: &[u8]) -> u16; fn read_u32(buf: &[u8]) -> u32; fn read_u64(buf: &[u8]) -> u64; fn read_uint(buf: &[u8], nbytes: usize) -> u64; fn write_u16(buf: &mut [u8], n: u16); fn write_u32(buf: &mut [u8], n: u32); fn write_u64(buf: &mut [u8], n: u64); fn write_uint(buf: &mut [u8], n: u64, nbytes: usize); } pub enum BigEndian {} pub enum LittleEndian {} pub enum NativeEndian {} macro_rules! impl_endian { ($t:ty, $from_endian:ident, $to_endian:ident) => { impl ByteOrder for $t { #[inline] fn read_u16(buf: &[u8]) -> u16 { u16::$from_endian(buf[0..2].try_into().unwrap()) } #[inline] fn read_u32(buf: &[u8]) -> u32 { u32::$from_endian(buf[0..4].try_into().unwrap()) } #[inline] fn read_u64(buf: &[u8]) -> u64 { u64::$from_endian(buf[0..8].try_into().unwrap()) } #[inline] fn read_uint(buf: &[u8], nbytes: usize) -> u64 { let mut dst = [0u8; 8]; dst[..nbytes].copy_from_slice(&buf[..nbytes]); u64::$from_endian(dst) } #[inline] fn write_u16(buf: &mut [u8], n: u16) { buf[0..2].copy_from_slice(&n.$to_endian()[..]); } #[inline] fn write_u32(buf: &mut [u8], n: u32) { buf[0..4].copy_from_slice(&n.$to_endian()[..]); } #[inline] fn write_u64(buf: &mut [u8], n: u64) { buf[0..8].copy_from_slice(&n.$to_endian()[..]); } #[inline] fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) { buf[..nbytes].copy_from_slice(&n.$to_endian()[..nbytes]); } } }; } impl_endian! { BigEndian, from_be_bytes, to_be_bytes } impl_endian! { LittleEndian, from_le_bytes, to_le_bytes } impl_endian! { NativeEndian, from_ne_bytes, to_ne_bytes }