#![feature(i128_type)]
pub fn write<T: Encode>(buf: &mut [u8], from: T) {
from.write_le(buf)
}
pub fn read<T: Decode>(buf: &[u8]) -> T {
T::read_le(buf)
}
pub trait Encode {
fn write_le(self, into: &mut [u8]);
}
pub trait Decode {
fn read_le(from: &[u8]) -> Self;
}
impl Decode for u8 {
fn read_le(from: &[u8]) -> u8 {
from[0]
}
}
impl Encode for u8 {
fn write_le(self, into: &mut [u8]) {
into[0] = self;
}
}
impl Decode for u16 {
fn read_le(from: &[u8]) -> u16 {
from[0] as u16
| (from[1] as u16) << 8
}
}
impl Encode for u16 {
fn write_le(self, into: &mut [u8]) {
into[0] = self as u8;
into[1] = (self >> 8) as u8;
}
}
impl Decode for u32 {
fn read_le(from: &[u8]) -> u32 {
from[0] as u32
| (from[1] as u32) << 8
| (from[2] as u32) << 16
| (from[3] as u32) << 24
}
}
impl Encode for u32 {
fn write_le(self, into: &mut [u8]) {
into[0] = self as u8;
into[1] = (self >> 8) as u8;
into[2] = (self >> 16) as u8;
into[3] = (self >> 24) as u8;
}
}
impl Decode for u64 {
fn read_le(from: &[u8]) -> u64 {
from[0] as u64
| (from[1] as u64) << 8
| (from[2] as u64) << 16
| (from[3] as u64) << 24
| (from[4] as u64) << 32
| (from[5] as u64) << 40
| (from[6] as u64) << 48
| (from[7] as u64) << 56
}
}
impl Encode for u64 {
fn write_le(self, into: &mut [u8]) {
into[0] = self as u8;
into[1] = (self >> 8) as u8;
into[2] = (self >> 16) as u8;
into[3] = (self >> 24) as u8;
into[4] = (self >> 32) as u8;
into[5] = (self >> 40) as u8;
into[6] = (self >> 48) as u8;
into[7] = (self >> 56) as u8;
}
}
impl Decode for u128 {
fn read_le(from: &[u8]) -> u128 {
from[0] as u128
| (from[1] as u128) << 8
| (from[2] as u128) << 16
| (from[3] as u128) << 24
| (from[4] as u128) << 32
| (from[5] as u128) << 40
| (from[6] as u128) << 48
| (from[7] as u128) << 56
| (from[8] as u128) << 64
| (from[9] as u128) << 72
| (from[10] as u128) << 80
| (from[11] as u128) << 88
| (from[12] as u128) << 96
| (from[13] as u128) << 104
| (from[14] as u128) << 112
| (from[15] as u128) << 120
}
}
impl Encode for u128 {
fn write_le(self, into: &mut [u8]) {
into[0] = self as u8;
into[1] = (self >> 8) as u8;
into[2] = (self >> 16) as u8;
into[3] = (self >> 24) as u8;
into[4] = (self >> 32) as u8;
into[5] = (self >> 40) as u8;
into[6] = (self >> 48) as u8;
into[7] = (self >> 56) as u8;
into[8] = (self >> 64) as u8;
into[9] = (self >> 72) as u8;
into[10] = (self >> 80) as u8;
into[11] = (self >> 88) as u8;
into[12] = (self >> 96) as u8;
into[13] = (self >> 104) as u8;
into[14] = (self >> 112) as u8;
into[15] = (self >> 120) as u8;
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::{ops, mem, fmt};
fn test_int<T>(n: T)
where T: Encode + Decode + Copy + PartialEq + ops::BitAnd<T, Output = T> + ops::Shr<T,
Output = T> + From<u8> + fmt::Debug {
let len = mem::size_of::<T>();
let mut buf = [0; 32];
write(&mut buf, n);
for i in 0..len {
assert_eq!(T::from(buf[i]), (n >> T::from(i as u8 * 8)) & T::from(0xFF));
}
assert_eq!(read::<T>(&buf), n);
}
#[test]
fn u8() {
test_int(12u8);
test_int(1u8);
test_int(0u8);
}
#[test]
fn u16() {
test_int::<u16>(0xAB);
test_int::<u16>(0xBA);
test_int::<u16>(0);
}
#[test]
fn u32() {
test_int::<u32>(0xABCD);
test_int::<u32>(0xDCBA);
test_int::<u32>(0);
}
#[test]
fn u64() {
test_int::<u64>(0xABCDEF0);
test_int::<u64>(0x0FEDCBA);
test_int::<u64>(0);
}
#[test]
fn u128() {
test_int::<u128>(0xABCDEF012345678);
test_int::<u128>(0x876543210FEDCBA);
test_int::<u128>(0);
}
}