use byteorder;
use byteorder::ByteOrder;
use std::fmt::Debug;
pub trait Endianity: Debug + Default + Clone + Copy + PartialEq + Eq {
fn is_big_endian(self) -> bool;
#[inline]
fn is_little_endian(self) -> bool {
!self.is_big_endian()
}
#[inline]
fn read_u16(self, buf: &[u8]) -> u16 {
if self.is_big_endian() {
byteorder::BigEndian::read_u16(buf)
} else {
byteorder::LittleEndian::read_u16(buf)
}
}
#[inline]
fn read_u32(self, buf: &[u8]) -> u32 {
if self.is_big_endian() {
byteorder::BigEndian::read_u32(buf)
} else {
byteorder::LittleEndian::read_u32(buf)
}
}
#[inline]
fn read_u64(self, buf: &[u8]) -> u64 {
if self.is_big_endian() {
byteorder::BigEndian::read_u64(buf)
} else {
byteorder::LittleEndian::read_u64(buf)
}
}
#[inline]
fn read_uint(&mut self, buf: &[u8]) -> u64 {
if self.is_big_endian() {
byteorder::BigEndian::read_uint(buf, buf.len())
} else {
byteorder::LittleEndian::read_uint(buf, buf.len())
}
}
#[inline]
fn read_i16(self, buf: &[u8]) -> i16 {
self.read_u16(buf) as i16
}
#[inline]
fn read_i32(self, buf: &[u8]) -> i32 {
self.read_u32(buf) as i32
}
#[inline]
fn read_i64(self, buf: &[u8]) -> i64 {
self.read_u64(buf) as i64
}
#[inline]
fn read_f32(self, buf: &[u8]) -> f32 {
f32::from_bits(self.read_u32(buf))
}
#[inline]
fn read_f64(self, buf: &[u8]) -> f64 {
f64::from_bits(self.read_u64(buf))
}
#[inline]
fn write_u16(self, buf: &mut [u8], n: u16) {
if self.is_big_endian() {
byteorder::BigEndian::write_u16(buf, n)
} else {
byteorder::LittleEndian::write_u16(buf, n)
}
}
#[inline]
fn write_u32(self, buf: &mut [u8], n: u32) {
if self.is_big_endian() {
byteorder::BigEndian::write_u32(buf, n)
} else {
byteorder::LittleEndian::write_u32(buf, n)
}
}
#[inline]
fn write_u64(self, buf: &mut [u8], n: u64) {
if self.is_big_endian() {
byteorder::BigEndian::write_u64(buf, n)
} else {
byteorder::LittleEndian::write_u64(buf, n)
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RunTimeEndian {
Little,
Big,
}
impl Default for RunTimeEndian {
#[cfg(target_endian = "little")]
#[inline]
fn default() -> RunTimeEndian {
RunTimeEndian::Little
}
#[cfg(target_endian = "big")]
#[inline]
fn default() -> RunTimeEndian {
RunTimeEndian::Big
}
}
impl Endianity for RunTimeEndian {
#[inline]
fn is_big_endian(self) -> bool {
self != RunTimeEndian::Little
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LittleEndian;
impl Default for LittleEndian {
#[inline]
fn default() -> LittleEndian {
LittleEndian
}
}
impl Endianity for LittleEndian {
#[inline]
fn is_big_endian(self) -> bool {
false
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BigEndian;
impl Default for BigEndian {
#[inline]
fn default() -> BigEndian {
BigEndian
}
}
impl Endianity for BigEndian {
#[inline]
fn is_big_endian(self) -> bool {
true
}
}
#[cfg(target_endian = "little")]
pub type NativeEndian = LittleEndian;
#[cfg(target_endian = "little")]
#[allow(non_upper_case_globals)]
#[doc(hidden)]
pub const NativeEndian: LittleEndian = LittleEndian;
#[cfg(target_endian = "big")]
pub type NativeEndian = BigEndian;
#[cfg(target_endian = "big")]
#[allow(non_upper_case_globals)]
#[doc(hidden)]
pub const NativeEndian: BigEndian = BigEndian;