1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum Endianness {
LittleEndian,
BigEndian
}
impl Endianness {
#[cfg( target_endian = "little" )]
pub const NATIVE: Endianness = Endianness::LittleEndian;
#[cfg( target_endian = "big" )]
pub const NATIVE: Endianness = Endianness::BigEndian;
}
impl Endianness {
#[inline(always)]
pub fn conversion_necessary( self ) -> bool {
self != Endianness::NATIVE
}
#[inline(always)]
pub fn swap_slice_u8( self, _: &mut [u8] ) {}
#[inline(always)]
pub fn swap_slice_i8( self, _: &mut [i8] ) {}
}
macro_rules! emit_wrapper {
($type:ty, $reader:ident, $swapper:ident, $slice_swapper:ident) => {
impl Endianness {
#[inline]
pub fn $reader( self, slice: &[u8] ) -> $type {
assert!( slice.len() == core::mem::size_of::< $type >() );
let mut value: $type = 0;
unsafe {
core::ptr::copy_nonoverlapping(
slice.as_ptr(),
&mut value as *mut $type as *mut u8,
core::mem::size_of::< $type >()
);
}
if self.conversion_necessary() {
value = value.swap_bytes();
}
value
}
#[inline]
pub fn $swapper( self, value: &mut $type ) {
if self.conversion_necessary() {
*value = value.swap_bytes();
}
}
#[inline]
pub fn $slice_swapper( self, slice: &mut [$type] ) {
if self.conversion_necessary() {
for value in slice {
*value = value.swap_bytes();
}
}
}
}
}
}
emit_wrapper!( u16, read_u16, swap_u16, swap_slice_u16 );
emit_wrapper!( u32, read_u32, swap_u32, swap_slice_u32 );
emit_wrapper!( u64, read_u64, swap_u64, swap_slice_u64 );
emit_wrapper!( u128, read_u128, swap_u128, swap_slice_u128 );
emit_wrapper!( i16, read_i16, swap_i16, swap_slice_i16 );
emit_wrapper!( i32, read_i32, swap_i32, swap_slice_i32 );
emit_wrapper!( i64, read_i64, swap_i64, swap_slice_i64 );
emit_wrapper!( i128, read_i128, swap_i128, swap_slice_i128 );
impl Endianness {
#[inline]
pub fn read_f32( self, slice: &[u8] ) -> f32 {
f32::from_bits( self.read_u32( slice ) )
}
#[inline]
pub fn read_f64( self, slice: &[u8] ) -> f64 {
f64::from_bits( self.read_u64( slice ) )
}
#[inline]
pub fn swap_f32( self, value: &mut f32 ) {
let value = unsafe {
&mut *(value as *mut f32 as *mut u32)
};
self.swap_u32( value );
}
#[inline]
pub fn swap_f64( self, value: &mut f64 ) {
let value = unsafe {
&mut *(value as *mut f64 as *mut u64)
};
self.swap_u64( value );
}
#[inline]
pub fn swap_slice_f32( self, slice: &mut [f32] ) {
let slice = unsafe {
core::slice::from_raw_parts_mut( slice.as_mut_ptr() as *mut u32, slice.len() )
};
self.swap_slice_u32( slice );
}
#[inline]
pub fn swap_slice_f64( self, slice: &mut [f64] ) {
let slice = unsafe {
core::slice::from_raw_parts_mut( slice.as_mut_ptr() as *mut u64, slice.len() )
};
self.swap_slice_u64( slice );
}
}