From 4c9601551cf9089830a40a1f6d753d8fd542525d Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 3 Jun 2019 11:13:25 +0100 Subject: [PATCH] Support AsByteSliceMut on Wrapping types --- src/lib.rs | 69 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1e1a3d4f61d..26d22473a75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,6 +92,7 @@ pub mod seq; use core::{mem, slice}; +use core::num::Wrapping; use distributions::{Distribution, Standard}; use distributions::uniform::{SampleUniform, UniformSampler, SampleBorrow}; @@ -398,6 +399,7 @@ impl AsByteSliceMut for [u8] { } macro_rules! impl_as_byte_slice { + () => {}; ($t:ty) => { impl AsByteSliceMut for [$t] { fn as_byte_slice_mut(&mut self) -> &mut [u8] { @@ -422,26 +424,47 @@ macro_rules! impl_as_byte_slice { } } } + + impl AsByteSliceMut for [Wrapping<$t>] { + fn as_byte_slice_mut(&mut self) -> &mut [u8] { + if self.len() == 0 { + unsafe { + // must not use null pointer + slice::from_raw_parts_mut(0x1 as *mut u8, 0) + } + } else { + unsafe { + slice::from_raw_parts_mut(self.as_mut_ptr() + as *mut u8, + self.len() * mem::size_of::<$t>() + ) + } + } + } + + fn to_le(&mut self) { + for x in self { + *x = Wrapping(x.0.to_le()); + } + } + } + }; + ($t:ty, $($tt:ty,)*) => { + impl_as_byte_slice!($t); + // TODO: this could replace above impl once Rust #32463 is fixed + // impl_as_byte_slice!(Wrapping<$t>); + impl_as_byte_slice!($($tt,)*); } } -impl_as_byte_slice!(u16); -impl_as_byte_slice!(u32); -impl_as_byte_slice!(u64); +impl_as_byte_slice!(u16, u32, u64, usize,); #[cfg(all(rustc_1_26, not(target_os = "emscripten")))] impl_as_byte_slice!(u128); -impl_as_byte_slice!(usize); -impl_as_byte_slice!(i8); -impl_as_byte_slice!(i16); -impl_as_byte_slice!(i32); -impl_as_byte_slice!(i64); +impl_as_byte_slice!(i8, i16, i32, i64, isize,); #[cfg(all(rustc_1_26, not(target_os = "emscripten")))] impl_as_byte_slice!(i128); -impl_as_byte_slice!(isize); macro_rules! impl_as_byte_slice_arrays { ($n:expr,) => {}; - ($n:expr, $N:ident, $($NN:ident,)*) => { - impl_as_byte_slice_arrays!($n - 1, $($NN,)*); - + ($n:expr, $N:ident) => { impl AsByteSliceMut for [T; $n] where [T]: AsByteSliceMut { fn as_byte_slice_mut(&mut self) -> &mut [u8] { self[..].as_byte_slice_mut() @@ -452,25 +475,19 @@ macro_rules! impl_as_byte_slice_arrays { } } }; + ($n:expr, $N:ident, $($NN:ident,)*) => { + impl_as_byte_slice_arrays!($n, $N); + impl_as_byte_slice_arrays!($n - 1, $($NN,)*); + }; (!div $n:expr,) => {}; (!div $n:expr, $N:ident, $($NN:ident,)*) => { + impl_as_byte_slice_arrays!($n, $N); impl_as_byte_slice_arrays!(!div $n / 2, $($NN,)*); - - impl AsByteSliceMut for [T; $n] where [T]: AsByteSliceMut { - fn as_byte_slice_mut(&mut self) -> &mut [u8] { - self[..].as_byte_slice_mut() - } - - fn to_le(&mut self) { - self[..].to_le() - } - } }; } impl_as_byte_slice_arrays!(32, N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,); impl_as_byte_slice_arrays!(!div 4096, N,N,N,N,N,N,N,); - /// Generates a random value using the thread-local random number generator. /// /// This is simply a shortcut for `thread_rng().gen()`. See [`thread_rng`] for @@ -568,6 +585,12 @@ mod test { rng.fill(&mut array[..]); assert_eq!(array, [x as u32, (x >> 32) as u32]); assert_eq!(rng.next_u32(), x as u32); + + // Check equivalence using wrapped arrays + let mut warray = [Wrapping(0u32); 2]; + rng.fill(&mut warray[..]); + assert_eq!(array[0], warray[0].0); + assert_eq!(array[1], warray[1].0); } #[test]