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
#[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!( 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 ); 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 ); } }