1use std::convert::TryInto;
2use std::io;
3
4#[inline]
7pub fn read_u32_le(slice: &[u8]) -> u32 {
8 u32::from_le_bytes(slice[..4].try_into().unwrap())
9}
10
11#[inline]
14pub fn read_u64_le(slice: &[u8]) -> u64 {
15 u64::from_le_bytes(slice[..8].try_into().unwrap())
16}
17
18#[inline]
21pub fn write_u32_le(n: u32, slice: &mut [u8]) {
22 assert!(slice.len() >= 4);
23 let bytes = n.to_le_bytes();
24 slice[0] = bytes[0];
25 slice[1] = bytes[1];
26 slice[2] = bytes[2];
27 slice[3] = bytes[3];
28}
29
30#[inline]
33pub fn io_write_u32_le<W: io::Write>(n: u32, mut wtr: W) -> io::Result<()> {
34 let mut buf = [0; 4];
35 write_u32_le(n, &mut buf);
36 wtr.write_all(&buf)
37}
38
39#[inline]
42pub fn write_u64_le(n: u64, slice: &mut [u8]) {
43 assert!(slice.len() >= 8);
44 let bytes = n.to_le_bytes();
45 slice[0] = bytes[0];
46 slice[1] = bytes[1];
47 slice[2] = bytes[2];
48 slice[3] = bytes[3];
49 slice[4] = bytes[4];
50 slice[5] = bytes[5];
51 slice[6] = bytes[6];
52 slice[7] = bytes[7];
53}
54
55#[inline]
58pub fn io_write_u64_le<W: io::Write>(n: u64, mut wtr: W) -> io::Result<()> {
59 let mut buf = [0; 8];
60 write_u64_le(n, &mut buf);
61 wtr.write_all(&buf)
62}
63
64#[inline]
68pub fn pack_uint<W: io::Write>(wtr: W, n: u64) -> io::Result<u8> {
69 let nbytes = pack_size(n);
70 pack_uint_in(wtr, n, nbytes).map(|_| nbytes)
71}
72
73#[inline]
79pub fn pack_uint_in<W: io::Write>(
80 mut wtr: W,
81 mut n: u64,
82 nbytes: u8,
83) -> io::Result<()> {
84 assert!(1 <= nbytes && nbytes <= 8);
85 let mut buf = [0u8; 8];
86 for i in 0..nbytes {
87 buf[i as usize] = n as u8;
88 n = n >> 8;
89 }
90 wtr.write_all(&buf[..nbytes as usize])?;
91 Ok(())
92}
93
94#[inline]
99pub fn unpack_uint(slice: &[u8], nbytes: u8) -> u64 {
100 assert!(1 <= nbytes && nbytes <= 8);
101
102 let mut n = 0;
103 for (i, &b) in slice[..nbytes as usize].iter().enumerate() {
104 n = n | ((b as u64) << (8 * i));
105 }
106 n
107}
108
109#[inline]
111pub fn pack_size(n: u64) -> u8 {
112 if n < 1 << 8 {
113 1
114 } else if n < 1 << 16 {
115 2
116 } else if n < 1 << 24 {
117 3
118 } else if n < 1 << 32 {
119 4
120 } else if n < 1 << 40 {
121 5
122 } else if n < 1 << 48 {
123 6
124 } else if n < 1 << 56 {
125 7
126 } else {
127 8
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134 use quickcheck::{QuickCheck, StdGen};
135 use std::io;
136
137 #[test]
138 fn prop_pack_in_out() {
139 fn p(num: u64) -> bool {
140 let mut buf = io::Cursor::new(vec![]);
141 let size = pack_uint(&mut buf, num).unwrap();
142 buf.set_position(0);
143 num == unpack_uint(buf.get_ref(), size)
144 }
145 QuickCheck::new()
146 .gen(StdGen::new(::rand::thread_rng(), 257)) .quickcheck(p as fn(u64) -> bool);
148 }
149}