endian.rs 4.9 KB

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