1macro_rules! define_slice_to_be {
20 ($name: ident, $type: ty) => {
21 #[inline]
22 #[allow(dead_code)]
23 pub fn $name(slice: &[u8]) -> $type {
24 assert_eq!(slice.len(), ::core::mem::size_of::<$type>());
25 let mut res = 0;
26 for i in 0..::core::mem::size_of::<$type>() {
27 res |= (slice[i] as $type) << (::core::mem::size_of::<$type>() - i - 1) * 8;
28 }
29 res
30 }
31 };
32}
33
34macro_rules! define_slice_to_le {
35 ($name: ident, $type: ty) => {
36 #[inline]
37 pub fn $name(slice: &[u8]) -> $type {
38 assert_eq!(slice.len(), ::core::mem::size_of::<$type>());
39 let mut res = 0;
40 for i in 0..::core::mem::size_of::<$type>() {
41 res |= (slice[i] as $type) << i * 8;
42 }
43 res
44 }
45 };
46}
47
48macro_rules! define_be_to_array {
49 ($name: ident, $type: ty, $byte_len: expr) => {
50 #[inline]
51 #[allow(dead_code)]
52 pub fn $name(val: $type) -> [u8; $byte_len] {
53 assert_eq!(::core::mem::size_of::<$type>(), $byte_len);
54 let mut res = [0; $byte_len];
55 for i in 0..$byte_len {
56 res[i] = ((val >> ($byte_len - i - 1) * 8) & 0xff) as u8;
57 }
58 res
59 }
60 };
61}
62
63macro_rules! define_le_to_array {
64 ($name: ident, $type: ty, $byte_len: expr) => {
65 #[inline]
66 pub fn $name(val: $type) -> [u8; $byte_len] {
67 assert_eq!(::core::mem::size_of::<$type>(), $byte_len);
68 let mut res = [0; $byte_len];
69 for i in 0..$byte_len {
70 res[i] = ((val >> i * 8) & 0xff) as u8;
71 }
72 res
73 }
74 };
75}
76
77define_slice_to_be!(slice_to_u32_be, u32);
78define_be_to_array!(u32_to_array_be, u32, 4);
79
80define_slice_to_le!(slice_to_u16_le, u16);
81define_slice_to_le!(slice_to_u32_le, u32);
82define_slice_to_le!(slice_to_u64_le, u64);
83define_slice_to_le!(slice_to_u128_le, u128);
84define_le_to_array!(u16_to_array_le, u16, 2);
88define_le_to_array!(u32_to_array_le, u32, 4);
89define_le_to_array!(u64_to_array_le, u64, 8);
90define_le_to_array!(u128_to_array_le, u128, 16);
91#[inline]
95pub fn i16_to_array_le(val: i16) -> [u8; 2] {
96 u16_to_array_le(val as u16)
97}
98
99#[inline]
100pub fn i32_to_array_le(val: i32) -> [u8; 4] {
101 u32_to_array_le(val as u32)
102}
103
104#[inline]
105pub fn i64_to_array_le(val: i64) -> [u8; 8] {
106 u64_to_array_le(val as u64)
107}
108
109#[inline]
110pub fn i128_to_array_le(val: i128) -> [u8; 16] {
111 u128_to_array_le(val as u128)
112}
113
114#[inline]
115pub fn slice_to_i16_le(slice: &[u8]) -> i16 {
116 slice_to_u16_le(slice) as i16
117}
118
119#[inline]
120pub fn slice_to_i32_le(slice: &[u8]) -> i32 {
121 slice_to_u32_le(slice) as i32
122}
123
124#[inline]
125pub fn slice_to_i64_le(slice: &[u8]) -> i64 {
126 slice_to_u64_le(slice) as i64
127}
128
129#[inline]
130pub fn slice_to_i128_le(slice: &[u8]) -> i128 {
131 slice_to_u128_le(slice) as i128
132}
133
134#[inline]
135pub fn f64_to_array_le(val: f64) -> [u8; 8] {
136 assert_eq!(::core::mem::size_of::<f64>(), 8);
137 val.to_le_bytes()
138}
139#[inline]
140pub fn slice_to_f64_le(slice: &[u8; 8]) -> f64 {
141 assert_eq!(slice.len(), ::core::mem::size_of::<f64>());
142 f64::from_le_bytes(*slice)
143}
144#[inline]
145pub fn f32_to_array_le(val: f32) -> [u8; 4] {
146 assert_eq!(::core::mem::size_of::<f32>(), 4);
147 val.to_le_bytes()
148}
149#[inline]
150pub fn slice_to_f32_le(slice: &[u8; 4]) -> f32 {
151 assert_eq!(slice.len(), ::core::mem::size_of::<f32>());
152 f32::from_le_bytes(*slice)
153}
154
155macro_rules! define_chunk_slice_to_int {
156 ($name: ident, $type: ty, $converter: ident) => {
157 #[inline]
158 #[allow(dead_code)]
159 pub fn $name(inp: &[u8], outp: &mut [$type]) {
160 assert_eq!(inp.len(), std::mem::size_of_val(outp));
162 for (outp_val, data_bytes) in
163 outp.iter_mut().zip(inp.chunks(::core::mem::size_of::<$type>()))
164 {
165 *outp_val = $converter(data_bytes);
166 }
167 }
168 };
169}
170
171define_chunk_slice_to_int!(bytes_to_u64_slice_le, u64, slice_to_u64_le);
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn endianness_test() {
179 assert_eq!(slice_to_u32_be(&[0xde, 0xad, 0xbe, 0xef]), 0xdeadbeef);
180 assert_eq!(u32_to_array_be(0xdeadbeef), [0xde, 0xad, 0xbe, 0xef]);
181
182 assert_eq!(slice_to_u16_le(&[0xad, 0xde]), 0xdead);
183 assert_eq!(slice_to_u32_le(&[0xef, 0xbe, 0xad, 0xde]), 0xdeadbeef);
184 assert_eq!(
185 slice_to_u64_le(&[0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b]),
186 0x1badcafedeadbeef
187 );
188 assert_eq!(u16_to_array_le(0xdead), [0xad, 0xde]);
189 assert_eq!(u32_to_array_le(0xdeadbeef), [0xef, 0xbe, 0xad, 0xde]);
190 assert_eq!(
191 u64_to_array_le(0x1badcafedeadbeef),
192 [0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b]
193 );
194 }
195
196 #[test]
197 fn endian_chunk_test() {
198 let inp = [
199 0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b, 0xfe, 0xca, 0xad, 0x1b, 0xce, 0xfa,
200 0x01, 0x02,
201 ];
202 let mut out = [0; 2];
203 bytes_to_u64_slice_le(&inp, &mut out);
204 assert_eq!(out, [0x1badcafedeadbeef, 0x0201face1badcafe]);
205 }
206}