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 126 127 128 129 130 131 132 133
#[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 ); 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_f16( self, slice: &mut [half::f16] ) { let slice = unsafe { core::slice::from_raw_parts_mut( slice.as_mut_ptr() as *mut u16, slice.len() ) }; self.swap_slice_u16( 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 ); } }