integer_encoding/
fixed.rs
1use std::mem::{size_of, transmute};
2
3pub trait FixedInt: Sized + Copy {
7 const REQUIRED_SPACE: usize;
8 fn required_space() -> usize;
10 fn encode_fixed(self, dst: &mut [u8]);
12 fn decode_fixed(src: &[u8]) -> Self;
14 fn encode_fixed_light<'a>(&'a self) -> &'a [u8];
17
18 fn encode_fixed_vec(self) -> Vec<u8> {
20 let mut v = Vec::new();
21 v.resize(Self::required_space(), 0);
22 self.encode_fixed(&mut v[..]);
23 v
24 }
25 fn decode_fixed_vec(v: &Vec<u8>) -> Self {
27 assert_eq!(v.len(), Self::required_space());
28 Self::decode_fixed(&v[..])
29 }
30}
31
32macro_rules! impl_fixedint {
33 ($t:ty) => {
34 impl FixedInt for $t {
35 const REQUIRED_SPACE: usize = size_of::<Self>();
36
37 fn required_space() -> usize {
38 Self::REQUIRED_SPACE
39 }
40
41 fn encode_fixed_light<'a>(&'a self) -> &'a [u8] {
42 return unsafe {
43 std::slice::from_raw_parts(
44 transmute::<&$t, *const u8>(&self),
45 Self::REQUIRED_SPACE,
46 )
47 };
48 }
49
50 fn encode_fixed(self, dst: &mut [u8]) {
51 assert_eq!(dst.len(), Self::REQUIRED_SPACE);
52
53 #[allow(unused_mut)]
54 let mut encoded =
55 unsafe { &*(&self as *const $t as *const [u8; Self::REQUIRED_SPACE]) };
56
57 #[cfg(target_endian = "big")]
58 if Self::REQUIRED_SPACE > 1 {
59 let mut encoded_rev = [0 as u8; Self::REQUIRED_SPACE];
60 encoded_rev.copy_from_slice(encoded);
61 encoded_rev.reverse();
62 dst.clone_from_slice(&encoded_rev);
63 return;
64 }
65
66 dst.clone_from_slice(encoded);
67 }
68
69 #[cfg(target_endian = "little")]
70 fn decode_fixed(src: &[u8]) -> $t {
71 unsafe { (src.as_ptr() as *const $t).read_unaligned() }
72 }
73
74 #[cfg(target_endian = "big")]
75 fn decode_fixed(src: &[u8]) -> $t {
76 match Self::REQUIRED_SPACE {
77 1 => unsafe { (src.as_ptr() as *const $t).read_unaligned() },
78 _ => {
79 let mut src_fin = [0 as u8; Self::REQUIRED_SPACE];
80 src_fin.copy_from_slice(src);
81 src_fin.reverse();
82 unsafe { (src_fin.as_ptr() as *const $t).read_unaligned() }
83 }
84 }
85 }
86 }
87 };
88}
89
90impl_fixedint!(usize);
91impl_fixedint!(u64);
92impl_fixedint!(u32);
93impl_fixedint!(u16);
94impl_fixedint!(u8);
95impl_fixedint!(isize);
96impl_fixedint!(i64);
97impl_fixedint!(i32);
98impl_fixedint!(i16);
99impl_fixedint!(i8);