diff options
author | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 |
---|---|---|
committer | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 |
commit | 1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch) | |
tree | 7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/rdrand | |
parent | 5ecd8cf2cba827454317368b68571df0d13d7842 (diff) | |
download | fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip |
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/rdrand')
-rw-r--r-- | vendor/rdrand/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/rdrand/Cargo.toml | 28 | ||||
-rw-r--r-- | vendor/rdrand/LICENSE | 12 | ||||
-rw-r--r-- | vendor/rdrand/README.mkd | 8 | ||||
-rw-r--r-- | vendor/rdrand/appveyor.yml | 27 | ||||
-rw-r--r-- | vendor/rdrand/benches/rdrand.rs | 49 | ||||
-rw-r--r-- | vendor/rdrand/benches/rdseed.rs | 49 | ||||
-rw-r--r-- | vendor/rdrand/benches/std.rs | 31 | ||||
-rw-r--r-- | vendor/rdrand/src/changelog.rs | 25 | ||||
-rw-r--r-- | vendor/rdrand/src/lib.rs | 472 |
10 files changed, 702 insertions, 0 deletions
diff --git a/vendor/rdrand/.cargo-checksum.json b/vendor/rdrand/.cargo-checksum.json new file mode 100644 index 0000000..c7b5a11 --- /dev/null +++ b/vendor/rdrand/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"f11ed31fc1b481c7d0e24251d7d60d34442f1d25747c887c49dc9fbad7e13e59","LICENSE":"00d7b0c8bf95ea93162fccc84da96b906b15add708eade04f7ee6141f7b53141","README.mkd":"93853e9e773543ed0d0cf696b5fb151b15bddc1ad9c39996c9eb11b20a3c7ff6","appveyor.yml":"f502d8a0755b98e904a40b07e8ba270bccd729045b03c24a7db0dfbb4047b515","benches/rdrand.rs":"f3684c360d43bc8a780868c0a3af43b20d56975e03575122cee87277787cc8d0","benches/rdseed.rs":"520097b15a3f11c0c6a357e6cd23add598be22f37839bbc71040b827b05d1064","benches/std.rs":"6a5b52b070b2a594e735aa617f16fc6a861e64534634cdb61801c3297444f6fe","src/changelog.rs":"644e08c06836ecdf94f9a43aec109e9f05f9d85f00541683c72d0d3893ff8d6a","src/lib.rs":"8fc306db8a304d24c28fcefaec1849c0d8bbca97417420af7b81449c352b2e92"},"package":"678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"}
\ No newline at end of file diff --git a/vendor/rdrand/Cargo.toml b/vendor/rdrand/Cargo.toml new file mode 100644 index 0000000..6b3c80a --- /dev/null +++ b/vendor/rdrand/Cargo.toml @@ -0,0 +1,28 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "rdrand" +version = "0.4.0" +authors = ["Simonas Kazlauskas <rdrand@kazlauskas.me>"] +description = "An implementation of random number generator based on rdrand and rdseed instructions" +documentation = "https://docs.rs/rdrand/0.4.0/" +keywords = ["rand", "rdrand", "rdseed", "random"] +license = "ISC" +repository = "https://github.com/nagisa/rust_rdrand/" +[dependencies.rand_core] +version = "0.3" +default-features = false + +[features] +default = ["std"] +std = [] diff --git a/vendor/rdrand/LICENSE b/vendor/rdrand/LICENSE new file mode 100644 index 0000000..4d6f40d --- /dev/null +++ b/vendor/rdrand/LICENSE @@ -0,0 +1,12 @@ +Copyright © 2014, Simonas Kazlauskas + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without +fee is hereby granted, provided that the above copyright notice and this permission notice appear +in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/vendor/rdrand/README.mkd b/vendor/rdrand/README.mkd new file mode 100644 index 0000000..55ab48b --- /dev/null +++ b/vendor/rdrand/README.mkd @@ -0,0 +1,8 @@ +An implementation of random number generators based on `rdrand` and `rdseed` instructions. + +The random number generators provided by this crate are fairly slow (the latency for these +instructions is pretty high), but provide high quality random bits. Caveat is: neither AMD’s +nor Intel’s designs are public and therefore are not verifiable for lack of backdoors. + +Unless you know what you are doing, use the random number generators provided by the `rand` +crate (such as `EntropyRng`) instead. diff --git a/vendor/rdrand/appveyor.yml b/vendor/rdrand/appveyor.yml new file mode 100644 index 0000000..2e915cf --- /dev/null +++ b/vendor/rdrand/appveyor.yml @@ -0,0 +1,27 @@ +environment: + matrix: + - TARGET: 1.30.0-x86_64-pc-windows-msvc + - TARGET: 1.30.0-i686-pc-windows-msvc + - TARGET: 1.30.0-x86_64-pc-windows-gnu + - TARGET: 1.30.0-i686-pc-windows-gnu + - TARGET: nightly-x86_64-pc-windows-msvc + - TARGET: nightly-i686-pc-windows-msvc +install: + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:TARGET}.exe" -FileName "rust.exe" + - ps: .\rust.exe /VERYSILENT /NORESTART /DIR="C:\rust" | Out-Null + - ps: $env:PATH="$env:PATH;C:\rust\bin" + - rustc -vV + - cargo -vV +build: off + +test_script: +- cargo test +- cargo test --no-default-features + +for: +- matrix: + only: + - TARGET: nightly-x86_64-pc-windows-msvc + - TARGET: nightly-i686-pc-windows-msvc + test_script: + - cargo bench diff --git a/vendor/rdrand/benches/rdrand.rs b/vendor/rdrand/benches/rdrand.rs new file mode 100644 index 0000000..7e70c23 --- /dev/null +++ b/vendor/rdrand/benches/rdrand.rs @@ -0,0 +1,49 @@ +#![feature(test)] +extern crate rand_core; +extern crate rdrand; +extern crate test; + +use rand_core::RngCore; +use test::Bencher; + +#[bench] +fn bench_u16(b : &mut Bencher) { + if let Ok(gen) = rdrand::RdRand::new() { + b.bytes = 2; + b.iter(|| { + gen.try_next_u16().unwrap() + }); + } +} + +#[bench] +fn bench_u32(b : &mut Bencher) { + if let Ok(mut gen) = rdrand::RdRand::new() { + b.bytes = 4; + b.iter(|| { + gen.next_u32() + }); + } +} + +#[bench] +fn bench_u64(b : &mut Bencher) { + if let Ok(mut gen) = rdrand::RdRand::new() { + b.bytes = 8; + b.iter(|| { + gen.next_u64() + }); + } +} + +#[bench] +fn bench_fill(b : &mut Bencher) { + if let Ok(mut gen) = rdrand::RdRand::new() { + let mut buffer = [0; 128]; + b.bytes = 128; + b.iter(|| { + gen.fill_bytes(&mut buffer); + buffer + }); + } +} diff --git a/vendor/rdrand/benches/rdseed.rs b/vendor/rdrand/benches/rdseed.rs new file mode 100644 index 0000000..6bf8ceb --- /dev/null +++ b/vendor/rdrand/benches/rdseed.rs @@ -0,0 +1,49 @@ +#![feature(test)] +extern crate rand_core; +extern crate rdrand; +extern crate test; + +use rand_core::RngCore; +use test::Bencher; + +#[bench] +fn bench_rdseed_u16(b : &mut Bencher) { + if let Ok(gen) = rdrand::RdSeed::new() { + b.bytes = 2; + b.iter(|| { + gen.try_next_u16().unwrap() + }); + } +} + +#[bench] +fn bench_rdseed_u32(b : &mut Bencher) { + if let Ok(mut gen) = rdrand::RdSeed::new() { + b.bytes = 4; + b.iter(|| { + gen.next_u32() + }); + } +} + +#[bench] +fn bench_rdseed_u64(b : &mut Bencher) { + if let Ok(mut gen) = rdrand::RdSeed::new() { + b.bytes = 8; + b.iter(|| { + gen.next_u64() + }); + } +} + +#[bench] +fn bench_fill(b : &mut Bencher) { + if let Ok(mut gen) = rdrand::RdSeed::new() { + let mut buffer = [0; 128]; + b.bytes = 128; + b.iter(|| { + gen.fill_bytes(&mut buffer); + buffer + }); + } +} diff --git a/vendor/rdrand/benches/std.rs b/vendor/rdrand/benches/std.rs new file mode 100644 index 0000000..3fa8fad --- /dev/null +++ b/vendor/rdrand/benches/std.rs @@ -0,0 +1,31 @@ +// #![feature(test)] +// extern crate rand; +// extern crate test; +// +// use test::Bencher; +// use test::black_box; +// use rand::Rng; +// use rand::StdRng; +// use rand::OsRng; +// +// // OsRng is supposed to be the default for crypto uses. +// #[bench] +// fn bench_osrng_u64(b : &mut Bencher) { +// if let Ok(mut gen) = OsRng::new() { +// b.bytes = 8; +// b.iter(|| { +// black_box(gen.next_u64()); +// }); +// } +// } +// +// // StdRng is the default for everything else. +// #[bench] +// fn bench_stdrng_u64(b : &mut Bencher) { +// if let Ok(mut gen) = StdRng::new() { +// b.bytes = 8; +// b.iter(|| { +// gen.next_u64(); +// }); +// } +// } diff --git a/vendor/rdrand/src/changelog.rs b/vendor/rdrand/src/changelog.rs new file mode 100644 index 0000000..503f738 --- /dev/null +++ b/vendor/rdrand/src/changelog.rs @@ -0,0 +1,25 @@ +//! Project changelog + +/// ## Breaking changes +/// +/// Crate gained an enabled-by-default `std` feature. If you relied on rdrand being `core`-able +/// change your dependency to appear as such: +/// +/// ```toml +/// rdrand = { version = "0.4", default-features = false } +/// ``` +/// +/// This is done so that an advantage of the common feature detection functionality could be +/// employed by users that are not constrained by `core`. This functionality is faster, caches the +/// results and is shared between all users of the functionality. +/// +/// For `core` usage the feature detection has also been improved and will not be done if e.g. +/// crate is built with `rdrand` instructions enabled globally. +pub mod r0_4_0 {} + +/// Crate now works on stable! +/// +/// ## Breaking changes +/// +/// * Updated to `rand_core = ^0.3`. +pub mod r0_3_0 {} diff --git a/vendor/rdrand/src/lib.rs b/vendor/rdrand/src/lib.rs new file mode 100644 index 0000000..423ae21 --- /dev/null +++ b/vendor/rdrand/src/lib.rs @@ -0,0 +1,472 @@ +// Copyright © 2014, Simonas Kazlauskas <rdrand@kazlauskas.me> +// +// Permission to use, copy, modify, and/or distribute this software for any purpose with or without +// fee is hereby granted, provided that the above copyright notice and this permission notice +// appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +// OF THIS SOFTWARE. +//! An implementation of random number generators based on `rdrand` and `rdseed` instructions. +//! +//! The random number generators provided by this crate are fairly slow (the latency for these +//! instructions is pretty high), but provide high quality random bits. Caveat is: neither AMD’s +//! nor Intel’s designs are public and therefore are not verifiable for lack of backdoors. +//! +//! Unless you know what you are doing, use the random number generators provided by the `rand` +//! crate (such as `OsRng`) instead. +//! +//! Here are a measurements for select processor architectures. Check [Agner’s instruction tables] +//! for up-to-date listings. +//! +//! <table> +//! <tr> +//! <th>Architecture</th> +//! <th colspan="3">Latency (cycles)</th> +//! <th>Maximum throughput (per core)</th> +//! </tr> +//! <tr> +//! <td></td> +//! <td>u16</td> +//! <td>u32</td> +//! <td>u64</td> +//! <td></td> +//! </tr> +//! <tr> +//! <td>AMD Ryzen</td> +//! <td>~1200</td> +//! <td>~1200</td> +//! <td>~2500</td> +//! <td>~12MB/s @ 3.7GHz</td> +//! </tr> +//! <tr> +//! <td>Intel Skylake</td> +//! <td>460</td> +//! <td>460</td> +//! <td>460</td> +//! <td>~72MB/s @ 4.2GHz</td> +//! </tr> +//! <tr> +//! <td>Intel Haswell</td> +//! <td>320</td> +//! <td>320</td> +//! <td>320</td> +//! <td>~110MB/s @ 4.4GHz</td> +//! </tr> +//! </table> +//! +//! [Agner’s instruction tables]: http://agner.org/optimize/ +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate rand_core; + +#[cfg(feature = "std")] +extern crate core; + +pub mod changelog; + +use rand_core::{RngCore, CryptoRng, Error, ErrorKind}; +use core::slice; + +const RETRY_LIMIT: u8 = 127; + +#[cold] +#[inline(never)] +pub(crate) fn busy_loop_fail() -> ! { + panic!("hardware generator failure"); +} + +/// A cryptographically secure statistically uniform, non-periodic and non-deterministic random bit +/// generator. +/// +/// Note that this generator may be implemented using a deterministic algorithm that is reseeded +/// routinely from a non-deterministic entropy source to achieve the desirable properties. +/// +/// This generator is a viable replacement to any generator, however, since nobody has audited +/// Intel or AMD hardware yet, the usual disclaimers as to their suitability apply. +/// +/// It is potentially faster than `OsRng`, but is only supported on more recent Intel (Ivy Bridge +/// and later) and AMD (Ryzen and later) processors. +#[derive(Clone, Copy)] +pub struct RdRand(()); + +/// A cryptographically secure non-deterministic random bit generator. +/// +/// This generator produces high-entropy output and is suited to seed other pseudo-random +/// generators. +/// +/// This instruction currently is only available in Intel Broadwell (and later) and AMD Ryzen +/// processors. +/// +/// This generator is not intended for general random number generation purposes and should be used +/// to seed other generators implementing [rand_core::SeedableRng]. +#[derive(Clone, Copy)] +pub struct RdSeed(()); + +impl CryptoRng for RdRand {} +impl CryptoRng for RdSeed {} + +mod arch { + #[cfg(target_arch = "x86_64")] + pub use core::arch::x86_64::*; + #[cfg(target_arch = "x86")] + pub use core::arch::x86::*; + + #[cfg(target_arch = "x86")] + pub(crate) unsafe fn _rdrand64_step(dest: &mut u64) -> i32 { + let mut ret1: u32 = ::core::mem::uninitialized(); + let mut ret2: u32 = ::core::mem::uninitialized(); + if _rdrand32_step(&mut ret1) != 0 && _rdrand32_step(&mut ret2) != 0 { + *dest = (ret1 as u64) << 32 | (ret2 as u64); + 1 + } else { + 0 + } + } + + #[cfg(target_arch = "x86")] + pub(crate) unsafe fn _rdseed64_step(dest: &mut u64) -> i32 { + let mut ret1: u32 = ::core::mem::uninitialized(); + let mut ret2: u32 = ::core::mem::uninitialized(); + if _rdseed32_step(&mut ret1) != 0 && _rdseed32_step(&mut ret2) != 0 { + *dest = (ret1 as u64) << 32 | (ret2 as u64); + 1 + } else { + 0 + } + } +} + +#[cfg(not(feature = "std"))] +macro_rules! is_x86_feature_detected { + ("rdrand") => {{ + if cfg!(target_feature="rdrand") { + true + } else if cfg!(target_env = "sgx") { + false + } else { + const FLAG : u32 = 1 << 30; + unsafe { ::arch::__cpuid(1).ecx & FLAG == FLAG } + } + }}; + ("rdseed") => {{ + if cfg!(target_feature = "rdseed") { + true + } else if cfg!(target_env = "sgx") { + false + } else { + const FLAG : u32 = 1 << 18; + unsafe { ::arch::__cpuid(7).ebx & FLAG == FLAG } + } + }}; +} + +macro_rules! loop_rand { + ($el: ty, $step: path) => { { + let mut idx = 0; + loop { + let mut el: $el = ::core::mem::uninitialized(); + if $step(&mut el) != 0 { + break Some(el); + } else if idx == RETRY_LIMIT { + break None; + } + idx += 1; + } + } } +} + +macro_rules! impl_rand { + ($gen:ident, $feat:tt, $step16: path, $step32:path, $step64:path, + maxstep = $maxstep:path, maxty = $maxty: ty) => { + impl $gen { + /// Create a new instance of the random number generator. + /// + /// This constructor checks whether the CPU the program is running on supports the + /// instruction necessary for this generator to operate. If the instruction is not + /// supported, an error is returned. + pub fn new() -> Result<Self, Error> { + if is_x86_feature_detected!($feat) { + Ok($gen(())) + } else { + Err(Error::new(rand_core::ErrorKind::Unavailable, + "the instruction is not supported")) + } + } + + /// Generate a single random `u16` value. + /// + /// The underlying instruction may fail for variety reasons (such as actual hardware + /// failure or exhausted entropy), however the exact reason for the failure is not + /// usually exposed. + /// + /// This method will retry calling the instruction a few times, however if all the + /// attempts fail, it will return `None`. + /// + /// In case `None` is returned, the caller should assume that an non-recoverable + /// hardware failure has occured and use another random number genrator instead. + #[inline(always)] + pub fn try_next_u16(&self) -> Option<u16> { + #[target_feature(enable = $feat)] + unsafe fn imp() + -> Option<u16> { + loop_rand!(u16, $step16) + } + unsafe { imp() } + } + + /// Generate a single random `u32` value. + /// + /// The underlying instruction may fail for variety reasons (such as actual hardware + /// failure or exhausted entropy), however the exact reason for the failure is not + /// usually exposed. + /// + /// This method will retry calling the instruction a few times, however if all the + /// attempts fail, it will return `None`. + /// + /// In case `None` is returned, the caller should assume that an non-recoverable + /// hardware failure has occured and use another random number genrator instead. + #[inline(always)] + pub fn try_next_u32(&self) -> Option<u32> { + #[target_feature(enable = $feat)] + unsafe fn imp() + -> Option<u32> { + loop_rand!(u32, $step32) + } + unsafe { imp() } + } + + /// Generate a single random `u64` value. + /// + /// The underlying instruction may fail for variety reasons (such as actual hardware + /// failure or exhausted entropy), however the exact reason for the failure is not + /// usually exposed. + /// + /// This method will retry calling the instruction a few times, however if all the + /// attempts fail, it will return `None`. + /// + /// In case `None` is returned, the caller should assume that an non-recoverable + /// hardware failure has occured and use another random number genrator instead. + /// + /// Note, that on 32-bit targets, there’s no underlying instruction to generate a + /// 64-bit number, so it is emulated with the 32-bit version of the instruction. + #[inline(always)] + pub fn try_next_u64(&self) -> Option<u64> { + #[target_feature(enable = $feat)] + unsafe fn imp() + -> Option<u64> { + loop_rand!(u64, $step64) + } + unsafe { imp() } + } + } + + impl RngCore for $gen { + /// Generate a single random `u32` value. + /// + /// The underlying instruction may fail for variety reasons (such as actual hardware + /// failure or exhausted entropy), however the exact reason for the failure is not + /// usually exposed. + /// + /// # Panic + /// + /// This method will retry calling the instruction a few times, however if all the + /// attempts fail, it will `panic`. + /// + /// In case `panic` occurs, the caller should assume that an non-recoverable + /// hardware failure has occured and use another random number genrator instead. + #[inline(always)] + fn next_u32(&mut self) -> u32 { + if let Some(result) = self.try_next_u32() { + result + } else { + busy_loop_fail() + } + } + + /// Generate a single random `u64` value. + /// + /// The underlying instruction may fail for variety reasons (such as actual hardware + /// failure or exhausted entropy), however the exact reason for the failure is not + /// usually exposed. + /// + /// Note, that on 32-bit targets, there’s no underlying instruction to generate a + /// 64-bit number, so it is emulated with the 32-bit version of the instruction. + /// + /// # Panic + /// + /// This method will retry calling the instruction a few times, however if all the + /// attempts fail, it will `panic`. + /// + /// In case `panic` occurs, the caller should assume that an non-recoverable + /// hardware failure has occured and use another random number genrator instead. + #[inline(always)] + fn next_u64(&mut self) -> u64 { + if let Some(result) = self.try_next_u64() { + result + } else { + busy_loop_fail() + } + } + + /// Fill a buffer `dest` with random data. + /// + /// See `try_fill_bytes` for a more extensive documentation. + /// + /// # Panic + /// + /// This method will panic any time `try_fill_bytes` would return an error. + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + if let Err(_) = self.try_fill_bytes(dest) { + busy_loop_fail() + } + } + + /// Fill a buffer `dest` with random data. + /// + /// This method will use the most appropriate variant of the instruction available on + /// the machine to achieve the greatest single-core throughput, however it has a + /// slightly higher setup cost than the plain `next_u32` or `next_u64` methods. + /// + /// The underlying instruction may fail for variety reasons (such as actual hardware + /// failure or exhausted entropy), however the exact reason for the failure is not + /// usually exposed. + /// + /// This method will retry calling the instruction a few times, however if all the + /// attempts fail, it will return an error. + /// + /// If an error is returned, the caller should assume that an non-recoverable hardware + /// failure has occured and use another random number genrator instead. + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) + -> Result<(), Error> { + #[target_feature(enable = $feat)] + unsafe fn imp(dest: &mut [u8]) + -> Result<(), Error> + { + unsafe fn imp_less_fast(mut dest: &mut [u8], word: &mut $maxty, + buffer: &mut &[u8]) + -> Result<(), Error> + { + while !dest.is_empty() { + if buffer.is_empty() { + if let Some(w) = loop_rand!($maxty, $maxstep) { + *word = w; + *buffer = slice::from_raw_parts( + word as *const _ as *const u8, + ::core::mem::size_of::<$maxty>() + ); + } else { + return Err(Error::new(ErrorKind::Unexpected, + "hardware generator failure")); + } + } + + let len = dest.len().min(buffer.len()); + let (copy_src, leftover) = buffer.split_at(len); + let (copy_dest, dest_leftover) = { dest }.split_at_mut(len); + *buffer = leftover; + dest = dest_leftover; + ::core::ptr::copy_nonoverlapping( + copy_src.as_ptr(), copy_dest.as_mut_ptr(), len + ); + } + Ok(()) + } + + let destlen = dest.len(); + if destlen > ::core::mem::size_of::<$maxty>() { + let (left, mid, right) = dest.align_to_mut(); + let mut word = 0; + let mut buffer: &[u8] = &[]; + + for el in mid { + if let Some(val) = loop_rand!($maxty, $maxstep) { + *el = val; + } else { + return Err(Error::new(ErrorKind::Unexpected, + "hardware generator failure")); + } + } + + imp_less_fast(left, &mut word, &mut buffer)?; + imp_less_fast(right, &mut word, &mut buffer) + } else { + let mut word = 0; + let mut buffer: &[u8] = &[]; + imp_less_fast(dest, &mut word, &mut buffer) + } + } + unsafe { imp(dest) } + } + } + } +} + +#[cfg(target_arch = "x86_64")] +impl_rand!(RdRand, "rdrand", + ::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step, + maxstep = ::arch::_rdrand64_step, maxty = u64); +#[cfg(target_arch = "x86_64")] +impl_rand!(RdSeed, "rdseed", + ::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step, + maxstep = ::arch::_rdseed64_step, maxty = u64); +#[cfg(target_arch = "x86")] +impl_rand!(RdRand, "rdrand", + ::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step, + maxstep = ::arch::_rdrand32_step, maxty = u32); +#[cfg(target_arch = "x86")] +impl_rand!(RdSeed, "rdseed", + ::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step, + maxstep = ::arch::_rdseed32_step, maxty = u32); + +#[test] +fn rdrand_works() { + let _ = RdRand::new().map(|mut r| { + r.next_u32(); + r.next_u64(); + }); +} + +#[test] +fn fill_fills_all_bytes() { + let _ = RdRand::new().map(|mut r| { + let mut peach; + let mut banana; + let mut start = 0; + let mut end = 128; + 'outer: while start < end { + banana = [0; 128]; + for _ in 0..512 { + peach = [0; 128]; + r.fill_bytes(&mut peach[start..end]); + for (b, p) in banana.iter_mut().zip(peach.iter()) { + *b = *b | *p; + } + if (&banana[start..end]).iter().all(|x| *x != 0) { + assert!(banana[..start].iter().all(|x| *x == 0), "all other values must be 0"); + assert!(banana[end..].iter().all(|x| *x == 0), "all other values must be 0"); + if start < 17 { + start += 1; + } else { + end -= 3; + } + continue 'outer; + } + } + panic!("wow, we broke it? {} {} {:?}", start, end, &banana[..]) + } + }); +} + +#[test] +fn rdseed_works() { + let _ = RdSeed::new().map(|mut r| { + r.next_u32(); + r.next_u64(); + }); +} |