From deb58862ddc0d02142abb4ffed6a966ada0fdec6 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Sun, 1 Apr 2018 10:58:57 -0400 Subject: style: remove all uses of transmute We should have done this from the start. Everything can be accomplished via pointer casts. Benchmarks show negligible differences. --- src/lib.rs | 134 +++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 96 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 9f668c5..d49d344 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,8 +47,8 @@ extern crate core; use core::fmt::Debug; use core::hash::Hash; -use core::mem::transmute; use core::ptr::copy_nonoverlapping; +use core::slice; #[cfg(feature = "std")] pub use io::{ReadBytesExt, WriteBytesExt}; @@ -629,7 +629,7 @@ pub trait ByteOrder /// ``` #[inline] fn read_f32(buf: &[u8]) -> f32 { - unsafe { transmute(Self::read_u32(buf)) } + unsafe { *(&Self::read_u32(buf) as *const u32 as *const f32) } } /// Reads a IEEE754 double-precision (8 bytes) floating point number. @@ -652,7 +652,7 @@ pub trait ByteOrder /// ``` #[inline] fn read_f64(buf: &[u8]) -> f64 { - unsafe { transmute(Self::read_u64(buf)) } + unsafe { *(&Self::read_u64(buf) as *const u64 as *const f64) } } /// Writes a signed 16 bit integer `n` to `buf`. @@ -833,7 +833,8 @@ pub trait ByteOrder /// ``` #[inline] fn write_f32(buf: &mut [u8], n: f32) { - Self::write_u32(buf, unsafe { transmute(n) }) + let n = unsafe { *(&n as *const f32 as *const u32) }; + Self::write_u32(buf, n) } /// Writes a IEEE754 double-precision (8 bytes) floating point number. @@ -856,7 +857,8 @@ pub trait ByteOrder /// ``` #[inline] fn write_f64(buf: &mut [u8], n: f64) { - Self::write_u64(buf, unsafe { transmute(n) }) + let n = unsafe { *(&n as *const f64 as *const u64) }; + Self::write_u64(buf, n) } /// Reads unsigned 16 bit integers from `src` into `dst`. @@ -975,7 +977,10 @@ pub trait ByteOrder /// ``` #[inline] fn read_i16_into(src: &[u8], dst: &mut [i16]) { - Self::read_u16_into(src, unsafe { transmute(dst) }); + let dst = unsafe { + slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u16, dst.len()) + }; + Self::read_u16_into(src, dst) } /// Reads signed 32 bit integers from `src` into `dst`. @@ -1001,7 +1006,10 @@ pub trait ByteOrder /// ``` #[inline] fn read_i32_into(src: &[u8], dst: &mut [i32]) { - Self::read_u32_into(src, unsafe { transmute(dst) }); + let dst = unsafe { + slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u32, dst.len()) + }; + Self::read_u32_into(src, dst); } /// Reads signed 64 bit integers from `src` into `dst`. @@ -1027,7 +1035,10 @@ pub trait ByteOrder /// ``` #[inline] fn read_i64_into(src: &[u8], dst: &mut [i64]) { - Self::read_u64_into(src, unsafe { transmute(dst) }); + let dst = unsafe { + slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u64, dst.len()) + }; + Self::read_u64_into(src, dst); } /// Reads signed 128 bit integers from `src` into `dst`. @@ -1054,7 +1065,10 @@ pub trait ByteOrder #[cfg(feature = "i128")] #[inline] fn read_i128_into(src: &[u8], dst: &mut [i128]) { - Self::read_u128_into(src, unsafe { transmute(dst) }); + let dst = unsafe { + slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u128, dst.len()) + }; + Self::read_u128_into(src, dst); } /// Reads IEEE754 single-precision (4 bytes) floating point numbers from @@ -1081,7 +1095,10 @@ pub trait ByteOrder /// ``` #[inline] fn read_f32_into_unchecked(src: &[u8], dst: &mut [f32]) { - Self::read_u32_into(src, unsafe { transmute(dst) }); + let dst = unsafe { + slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u32, dst.len()) + }; + Self::read_u32_into(src, dst); } /// Reads IEEE754 single-precision (4 bytes) floating point numbers from @@ -1108,7 +1125,10 @@ pub trait ByteOrder /// ``` #[inline] fn read_f64_into_unchecked(src: &[u8], dst: &mut [f64]) { - Self::read_u64_into(src, unsafe { transmute(dst) }); + let dst = unsafe { + slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u64, dst.len()) + }; + Self::read_u64_into(src, dst); } /// Writes unsigned 16 bit integers from `src` into `dst`. @@ -1226,7 +1246,10 @@ pub trait ByteOrder /// assert_eq!(numbers_given, numbers_got); /// ``` fn write_i16_into(src: &[i16], dst: &mut [u8]) { - Self::write_u16_into(unsafe { transmute(src) }, dst); + let src = unsafe { + slice::from_raw_parts(src.as_ptr() as *const u16, src.len()) + }; + Self::write_u16_into(src, dst); } /// Writes signed 32 bit integers from `src` into `dst`. @@ -1251,7 +1274,10 @@ pub trait ByteOrder /// assert_eq!(numbers_given, numbers_got); /// ``` fn write_i32_into(src: &[i32], dst: &mut [u8]) { - Self::write_u32_into(unsafe { transmute(src) }, dst); + let src = unsafe { + slice::from_raw_parts(src.as_ptr() as *const u32, src.len()) + }; + Self::write_u32_into(src, dst); } /// Writes signed 64 bit integers from `src` into `dst`. @@ -1276,7 +1302,10 @@ pub trait ByteOrder /// assert_eq!(numbers_given, numbers_got); /// ``` fn write_i64_into(src: &[i64], dst: &mut [u8]) { - Self::write_u64_into(unsafe { transmute(src) }, dst); + let src = unsafe { + slice::from_raw_parts(src.as_ptr() as *const u64, src.len()) + }; + Self::write_u64_into(src, dst); } /// Writes signed 128 bit integers from `src` into `dst`. @@ -1302,7 +1331,10 @@ pub trait ByteOrder /// ``` #[cfg(feature = "i128")] fn write_i128_into(src: &[i128], dst: &mut [u8]) { - Self::write_u128_into(unsafe { transmute(src) }, dst); + let src = unsafe { + slice::from_raw_parts(src.as_ptr() as *const u128, src.len()) + }; + Self::write_u128_into(src, dst); } /// Writes IEEE754 single-precision (4 bytes) floating point numbers from @@ -1330,7 +1362,10 @@ pub trait ByteOrder /// assert_eq!(numbers_given, numbers_got); /// ``` fn write_f32_into(src: &[f32], dst: &mut [u8]) { - Self::write_u32_into(unsafe { transmute(src) }, dst); + let src = unsafe { + slice::from_raw_parts(src.as_ptr() as *const u32, src.len()) + }; + Self::write_u32_into(src, dst); } /// Writes IEEE754 double-precision (8 bytes) floating point numbers from @@ -1358,7 +1393,10 @@ pub trait ByteOrder /// assert_eq!(numbers_given, numbers_got); /// ``` fn write_f64_into(src: &[f64], dst: &mut [u8]) { - Self::write_u64_into(unsafe { transmute(src) }, dst); + let src = unsafe { + slice::from_raw_parts(src.as_ptr() as *const u64, src.len()) + }; + Self::write_u64_into(src, dst); } /// Converts the given slice of unsigned 16 bit integers to a particular @@ -1478,8 +1516,11 @@ pub trait ByteOrder /// } /// ``` #[inline] - fn from_slice_i16(numbers: &mut [i16]) { - Self::from_slice_u16(unsafe { transmute(numbers) }); + fn from_slice_i16(src: &mut [i16]) { + let src = unsafe { + slice::from_raw_parts_mut(src.as_ptr() as *mut u16, src.len()) + }; + Self::from_slice_u16(src); } /// Converts the given slice of signed 32 bit integers to a particular @@ -1504,8 +1545,11 @@ pub trait ByteOrder /// } /// ``` #[inline] - fn from_slice_i32(numbers: &mut [i32]) { - Self::from_slice_u32(unsafe { transmute(numbers) }); + fn from_slice_i32(src: &mut [i32]) { + let src = unsafe { + slice::from_raw_parts_mut(src.as_ptr() as *mut u32, src.len()) + }; + Self::from_slice_u32(src); } /// Converts the given slice of signed 64 bit integers to a particular @@ -1530,8 +1574,11 @@ pub trait ByteOrder /// } /// ``` #[inline] - fn from_slice_i64(numbers: &mut [i64]) { - Self::from_slice_u64(unsafe { transmute(numbers) }); + fn from_slice_i64(src: &mut [i64]) { + let src = unsafe { + slice::from_raw_parts_mut(src.as_ptr() as *mut u64, src.len()) + }; + Self::from_slice_u64(src); } /// Converts the given slice of signed 128 bit integers to a particular @@ -1559,8 +1606,11 @@ pub trait ByteOrder /// ``` #[cfg(feature = "i128")] #[inline] - fn from_slice_i128(numbers: &mut [i128]) { - Self::from_slice_u128(unsafe { transmute(numbers) }); + fn from_slice_i128(src: &mut [i128]) { + let src = unsafe { + slice::from_raw_parts_mut(src.as_ptr() as *mut u128, src.len()) + }; + Self::from_slice_u128(src); } /// Converts the given slice of IEEE754 single-precision (4 bytes) floating @@ -1692,7 +1742,7 @@ macro_rules! write_num_bytes { assert!($size <= $dst.len()); unsafe { // N.B. https://github.com/rust-lang/rust/issues/22776 - let bytes = transmute::<_, [u8; $size]>($n.$which()); + let bytes = *(&$n.$which() as *const _ as *const [u8; $size]); copy_nonoverlapping((&bytes).as_ptr(), $dst.as_mut_ptr(), $size); } }); @@ -1812,7 +1862,7 @@ impl ByteOrder for BigEndian { assert!(pack_size(n) <= nbytes && nbytes <= 8); assert!(nbytes <= buf.len()); unsafe { - let bytes: [u8; 8] = transmute(n.to_be()); + let bytes = *(&n.to_be() as *const u64 as *const [u8; 8]); copy_nonoverlapping( bytes.as_ptr().offset((8 - nbytes) as isize), buf.as_mut_ptr(), @@ -1826,7 +1876,7 @@ impl ByteOrder for BigEndian { assert!(pack_size128(n) <= nbytes && nbytes <= 16); assert!(nbytes <= buf.len()); unsafe { - let bytes: [u8; 16] = transmute(n.to_be()); + let bytes = *(&n.to_be() as *const u128 as *const [u8; 16]); copy_nonoverlapping( bytes.as_ptr().offset((16 - nbytes) as isize), buf.as_mut_ptr(), @@ -1933,8 +1983,10 @@ impl ByteOrder for BigEndian { fn from_slice_f32(numbers: &mut [f32]) { if cfg!(target_endian = "little") { for n in numbers { - let int: u32 = unsafe { transmute(*n) }; - *n = unsafe { transmute(int.to_be()) }; + unsafe { + let int = *(n as *const f32 as *const u32); + *n = *(&int.to_be() as *const u32 as *const f32); + } } } } @@ -1943,8 +1995,10 @@ impl ByteOrder for BigEndian { fn from_slice_f64(numbers: &mut [f64]) { if cfg!(target_endian = "little") { for n in numbers { - let int: u64 = unsafe { transmute(*n) }; - *n = unsafe { transmute(int.to_be()) }; + unsafe { + let int = *(n as *const f64 as *const u64); + *n = *(&int.to_be() as *const u64 as *const f64); + } } } } @@ -2021,7 +2075,7 @@ impl ByteOrder for LittleEndian { assert!(pack_size(n as u64) <= nbytes && nbytes <= 8); assert!(nbytes <= buf.len()); unsafe { - let bytes: [u8; 8] = transmute(n.to_le()); + let bytes = *(&n.to_le() as *const u64 as *const [u8; 8]); copy_nonoverlapping(bytes.as_ptr(), buf.as_mut_ptr(), nbytes); } } @@ -2032,7 +2086,7 @@ impl ByteOrder for LittleEndian { assert!(pack_size128(n as u128) <= nbytes && nbytes <= 16); assert!(nbytes <= buf.len()); unsafe { - let bytes: [u8; 16] = transmute(n.to_le()); + let bytes = *(&n.to_le() as *const u128 as *const [u8; 16]); copy_nonoverlapping(bytes.as_ptr(), buf.as_mut_ptr(), nbytes); } } @@ -2136,8 +2190,10 @@ impl ByteOrder for LittleEndian { fn from_slice_f32(numbers: &mut [f32]) { if cfg!(target_endian = "big") { for n in numbers { - let int: u32 = unsafe { transmute(*n) }; - *n = unsafe { transmute(int.to_le()) }; + unsafe { + let int = *(n as *const f32 as *const u32); + *n = *(&int.to_le() as *const u32 as *const f32); + } } } } @@ -2146,8 +2202,10 @@ impl ByteOrder for LittleEndian { fn from_slice_f64(numbers: &mut [f64]) { if cfg!(target_endian = "big") { for n in numbers { - let int: u64 = unsafe { transmute(*n) }; - *n = unsafe { transmute(int.to_le()) }; + unsafe { + let int = *(n as *const f64 as *const u64); + *n = *(&int.to_le() as *const u64 as *const f64); + } } } } -- cgit v1.2.3