#![no_std]
#![feature(core_intrinsics)]
use core::intrinsics::transmute;
pub trait Swappable {}
impl Swappable for u128 {}
impl Swappable for u64 {}
impl Swappable for u32 {}
impl Swappable for u16 {}
impl Swappable for i128 {}
impl Swappable for i64 {}
impl Swappable for i32 {}
impl Swappable for i16 {}
impl Swappable for usize {}
impl Swappable for isize {}
impl Swappable for f32 {}
impl Swappable for f64 {}
#[derive(Debug, Clone, Copy)]
pub struct LittleEndian<T: Swappable>(T);
#[derive(Debug, Clone, Copy)]
pub struct BigEndian<T: Swappable>(T);
macro_rules! into_from {
($type: ident, $end: ident, $a: tt, $b: tt, $swap: tt) => {
impl Into<$type> for $end<$type> {
fn into(self) -> $type {
#[cfg(target_endian = $a)]
return self.0;
#[cfg(target_endian = $b)]
return unsafe { transmute(self.0.$swap()) };
}
}
impl From<$type> for $end<$type> {
fn from(value: $type) -> Self {
#[cfg(target_endian = $a)]
return Self(value);
#[cfg(target_endian = $b)]
return Self(unsafe { transmute(value.$swap()) });
}
}
};
}
macro_rules! le_into_from {
($type: ident) => {
into_from! {$type, LittleEndian, "little", "big", to_le_bytes}
};
}
macro_rules! be_into_from {
($type: ident) => {
into_from! {$type, BigEndian, "big", "little", to_be_bytes}
};
}
le_into_from! {u16}
le_into_from! {u32}
le_into_from! {u64}
le_into_from! {u128}
le_into_from! {usize}
le_into_from! {i16}
le_into_from! {i32}
le_into_from! {i64}
le_into_from! {i128}
le_into_from! {isize}
le_into_from! {f32}
le_into_from! {f64}
be_into_from! {u16}
be_into_from! {u32}
be_into_from! {u64}
be_into_from! {u128}
be_into_from! {usize}
be_into_from! {i16}
be_into_from! {i32}
be_into_from! {i64}
be_into_from! {i128}
be_into_from! {isize}
be_into_from! {f32}
be_into_from! {f64}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! test_type {
($fun: ident, $type: ident, $val: expr, $rev: expr) => {
#[test]
fn $fun() {
let l: LittleEndian<$type> = $val.into();
#[cfg(target_endian = "little")]
assert_eq!(l.0, $val);
#[cfg(target_endian = "big")]
assert_eq!(l.0, $rev);
let b: BigEndian<$type> = $val.into();
#[cfg(target_endian = "little")]
assert_eq!(b.0, $rev);
#[cfg(target_endian = "big")]
assert_eq!(b.0, $val);
}
};
}
test_type! {test_u128, u128, 0xaa000000000000000000000000000000, 0x000000000000000000000000000000aa}
test_type! {test_u64, u64, 0xaa00000000000000, 0x00000000000000aa}
test_type! {test_u32, u32, 0xaa000000, 0x000000aa}
test_type! {test_u16, u16, 0xaa00, 0x00aa}
#[cfg(target_pointer_width = "32")]
test_type! {test_usize, usize, 0xaa000000, 0x000000aa}
#[cfg(target_pointer_width = "64")]
test_type! {test_usize, usize, 0xaa00000000000000, 0x00000000000000aa}
#[cfg(target_pointer_width = "32")]
test_type! {test_isize, isize, -2isize, -16777217isize}
#[cfg(target_pointer_width = "64")]
test_type! {test_isize, isize, -2isize, -72057594037927937isize}
test_type! {test_i16, i16, -2i16, -257i16}
test_type! {test_i32, i32, -2i32, -16777217i32}
test_type! {test_i64, i64, -2i64, -72057594037927937i64}
test_type! {test_i128, i128, -2i128, -1329227995784915872903807060280344577i128}
test_type! {test_f32, f32, 1.3_f32, 272302750000000000000000_f32}
test_type! {test_f64, f64, 1.3_f64, -6065988000116450000000000000000000000000000000000000000000000000000_f64}
}