use std::convert::TryInto;
use std::io;
#[inline]
pub fn read_u32_le(slice: &[u8]) -> u32 {
u32::from_le_bytes(slice[..4].try_into().unwrap())
}
#[inline]
pub fn read_u64_le(slice: &[u8]) -> u64 {
u64::from_le_bytes(slice[..8].try_into().unwrap())
}
#[inline]
pub fn write_u32_le(n: u32, slice: &mut [u8]) {
assert!(slice.len() >= 4);
let bytes = n.to_le_bytes();
slice[0] = bytes[0];
slice[1] = bytes[1];
slice[2] = bytes[2];
slice[3] = bytes[3];
}
#[inline]
pub fn io_write_u32_le<W: io::Write>(n: u32, mut wtr: W) -> io::Result<()> {
let mut buf = [0; 4];
write_u32_le(n, &mut buf);
wtr.write_all(&buf)
}
#[inline]
pub fn write_u64_le(n: u64, slice: &mut [u8]) {
assert!(slice.len() >= 8);
let bytes = n.to_le_bytes();
slice[0] = bytes[0];
slice[1] = bytes[1];
slice[2] = bytes[2];
slice[3] = bytes[3];
slice[4] = bytes[4];
slice[5] = bytes[5];
slice[6] = bytes[6];
slice[7] = bytes[7];
}
#[inline]
pub fn io_write_u64_le<W: io::Write>(n: u64, mut wtr: W) -> io::Result<()> {
let mut buf = [0; 8];
write_u64_le(n, &mut buf);
wtr.write_all(&buf)
}
#[inline]
pub fn pack_uint<W: io::Write>(wtr: W, n: u64) -> io::Result<u8> {
let nbytes = pack_size(n);
pack_uint_in(wtr, n, nbytes).map(|_| nbytes)
}
#[inline]
pub fn pack_uint_in<W: io::Write>(
mut wtr: W,
mut n: u64,
nbytes: u8,
) -> io::Result<()> {
assert!(1 <= nbytes && nbytes <= 8);
let mut buf = [0u8; 8];
for i in 0..nbytes {
buf[i as usize] = n as u8;
n = n >> 8;
}
wtr.write_all(&buf[..nbytes as usize])?;
Ok(())
}
#[inline]
pub fn unpack_uint(slice: &[u8], nbytes: u8) -> u64 {
assert!(1 <= nbytes && nbytes <= 8);
let mut n = 0;
for (i, &b) in slice[..nbytes as usize].iter().enumerate() {
n = n | ((b as u64) << (8 * i));
}
n
}
#[inline]
pub fn pack_size(n: u64) -> u8 {
if n < 1 << 8 {
1
} else if n < 1 << 16 {
2
} else if n < 1 << 24 {
3
} else if n < 1 << 32 {
4
} else if n < 1 << 40 {
5
} else if n < 1 << 48 {
6
} else if n < 1 << 56 {
7
} else {
8
}
}
#[cfg(test)]
mod tests {
use super::*;
use quickcheck::{QuickCheck, StdGen};
use std::io;
#[test]
fn prop_pack_in_out() {
fn p(num: u64) -> bool {
let mut buf = io::Cursor::new(vec![]);
let size = pack_uint(&mut buf, num).unwrap();
buf.set_position(0);
num == unpack_uint(buf.get_ref(), size)
}
QuickCheck::new()
.gen(StdGen::new(::rand::thread_rng(), 257)) .quickcheck(p as fn(u64) -> bool);
}
}