endian.rs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. macro_rules! define_slice_to_be {
  2. ($name: ident, $type: ty) => {
  3. #[inline]
  4. #[allow(dead_code)]
  5. pub fn $name(slice: &[u8]) -> $type {
  6. assert_eq!(slice.len(), ::core::mem::size_of::<$type>());
  7. let mut res = 0;
  8. for i in 0..::core::mem::size_of::<$type>() {
  9. res |= (slice[i] as $type) << (::core::mem::size_of::<$type>() - i - 1) * 8;
  10. }
  11. res
  12. }
  13. };
  14. }
  15. macro_rules! define_slice_to_le {
  16. ($name: ident, $type: ty) => {
  17. #[inline]
  18. pub fn $name(slice: &[u8]) -> $type {
  19. assert_eq!(slice.len(), ::core::mem::size_of::<$type>());
  20. let mut res = 0;
  21. for i in 0..::core::mem::size_of::<$type>() {
  22. res |= (slice[i] as $type) << i * 8;
  23. }
  24. res
  25. }
  26. };
  27. }
  28. macro_rules! define_be_to_array {
  29. ($name: ident, $type: ty, $byte_len: expr) => {
  30. #[inline]
  31. #[allow(dead_code)]
  32. pub fn $name(val: $type) -> [u8; $byte_len] {
  33. assert_eq!(::core::mem::size_of::<$type>(), $byte_len);
  34. let mut res = [0; $byte_len];
  35. for i in 0..$byte_len {
  36. res[i] = ((val >> ($byte_len - i - 1) * 8) & 0xff) as u8;
  37. }
  38. res
  39. }
  40. };
  41. }
  42. macro_rules! define_le_to_array {
  43. ($name: ident, $type: ty, $byte_len: expr) => {
  44. #[inline]
  45. pub fn $name(val: $type) -> [u8; $byte_len] {
  46. assert_eq!(::core::mem::size_of::<$type>(), $byte_len);
  47. let mut res = [0; $byte_len];
  48. for i in 0..$byte_len {
  49. res[i] = ((val >> i * 8) & 0xff) as u8;
  50. }
  51. res
  52. }
  53. };
  54. }
  55. define_slice_to_be!(slice_to_u32_be, u32);
  56. define_be_to_array!(u32_to_array_be, u32, 4);
  57. define_slice_to_le!(slice_to_u16_le, u16);
  58. define_slice_to_le!(slice_to_u32_le, u32);
  59. define_slice_to_le!(slice_to_u64_le, u64);
  60. define_slice_to_le!(slice_to_u128_le, u128);
  61. define_slice_to_le!(slice_to_usize_le, usize);
  62. define_slice_to_le!(slice_to_isize_le, isize);
  63. define_le_to_array!(u16_to_array_le, u16, 2);
  64. define_le_to_array!(u32_to_array_le, u32, 4);
  65. define_le_to_array!(u64_to_array_le, u64, 8);
  66. define_le_to_array!(u128_to_array_le, u128, 16);
  67. define_le_to_array!(usize_to_array_le, usize, usize::BITS as usize / 8);
  68. define_le_to_array!(isize_to_array_le, isize, isize::BITS as usize / 8);
  69. #[inline]
  70. pub fn i16_to_array_le(val: i16) -> [u8; 2] {
  71. u16_to_array_le(val as u16)
  72. }
  73. #[inline]
  74. pub fn i32_to_array_le(val: i32) -> [u8; 4] {
  75. u32_to_array_le(val as u32)
  76. }
  77. #[inline]
  78. pub fn i64_to_array_le(val: i64) -> [u8; 8] {
  79. u64_to_array_le(val as u64)
  80. }
  81. #[inline]
  82. pub fn i128_to_array_le(val: i128) -> [u8; 16] {
  83. u128_to_array_le(val as u128)
  84. }
  85. #[inline]
  86. pub fn slice_to_i16_le(slice: &[u8]) -> i16 {
  87. slice_to_u16_le(slice) as i16
  88. }
  89. #[inline]
  90. pub fn slice_to_i32_le(slice: &[u8]) -> i32 {
  91. slice_to_u32_le(slice) as i32
  92. }
  93. #[inline]
  94. pub fn slice_to_i64_le(slice: &[u8]) -> i64 {
  95. slice_to_u64_le(slice) as i64
  96. }
  97. #[inline]
  98. pub fn slice_to_i128_le(slice: &[u8]) -> i128 {
  99. slice_to_u128_le(slice) as i128
  100. }
  101. #[inline]
  102. pub fn f64_to_array_le(val: f64) -> [u8; 8] {
  103. assert_eq!(::core::mem::size_of::<f64>(), 8);
  104. val.to_le_bytes()
  105. }
  106. #[inline]
  107. pub fn slice_to_f64_le(slice: &[u8; 8]) -> f64 {
  108. assert_eq!(slice.len(), ::core::mem::size_of::<f64>());
  109. f64::from_le_bytes(*slice)
  110. }
  111. #[inline]
  112. pub fn f32_to_array_le(val: f32) -> [u8; 4] {
  113. assert_eq!(::core::mem::size_of::<f32>(), 4);
  114. val.to_le_bytes()
  115. }
  116. #[inline]
  117. pub fn slice_to_f32_le(slice: &[u8; 4]) -> f32 {
  118. assert_eq!(slice.len(), ::core::mem::size_of::<f32>());
  119. f32::from_le_bytes(*slice)
  120. }
  121. macro_rules! define_chunk_slice_to_int {
  122. ($name: ident, $type: ty, $converter: ident) => {
  123. #[inline]
  124. #[allow(dead_code)]
  125. pub fn $name(inp: &[u8], outp: &mut [$type]) {
  126. assert_eq!(inp.len(), outp.len() * ::core::mem::size_of::<$type>());
  127. for (outp_val, data_bytes) in
  128. outp.iter_mut().zip(inp.chunks(::core::mem::size_of::<$type>()))
  129. {
  130. *outp_val = $converter(data_bytes);
  131. }
  132. }
  133. };
  134. }
  135. define_chunk_slice_to_int!(bytes_to_u64_slice_le, u64, slice_to_u64_le);
  136. #[cfg(test)]
  137. mod tests {
  138. use super::*;
  139. #[test]
  140. fn endianness_test() {
  141. assert_eq!(slice_to_u32_be(&[0xde, 0xad, 0xbe, 0xef]), 0xdeadbeef);
  142. assert_eq!(u32_to_array_be(0xdeadbeef), [0xde, 0xad, 0xbe, 0xef]);
  143. assert_eq!(slice_to_u16_le(&[0xad, 0xde]), 0xdead);
  144. assert_eq!(slice_to_u32_le(&[0xef, 0xbe, 0xad, 0xde]), 0xdeadbeef);
  145. assert_eq!(
  146. slice_to_u64_le(&[0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b]),
  147. 0x1badcafedeadbeef
  148. );
  149. assert_eq!(u16_to_array_le(0xdead), [0xad, 0xde]);
  150. assert_eq!(u32_to_array_le(0xdeadbeef), [0xef, 0xbe, 0xad, 0xde]);
  151. assert_eq!(
  152. u64_to_array_le(0x1badcafedeadbeef),
  153. [0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b]
  154. );
  155. }
  156. #[test]
  157. fn endian_chunk_test() {
  158. let inp = [
  159. 0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b, 0xfe, 0xca, 0xad, 0x1b, 0xce, 0xfa,
  160. 0x01, 0x02,
  161. ];
  162. let mut out = [0; 2];
  163. bytes_to_u64_slice_le(&inp, &mut out);
  164. assert_eq!(out, [0x1badcafedeadbeef, 0x0201face1badcafe]);
  165. }
  166. }