diff --git a/.travis.yml b/.travis.yml index 2360b235c53..671d6d668fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,8 +66,8 @@ matrix: # TODO: add simd_support feature: - cargo test --features=serde1,log - cargo test --examples - - cargo test --manifest-path rand_core/Cargo.toml - - cargo test --manifest-path rand_core/Cargo.toml --no-default-features + - cargo test --manifest-path rand_core/Cargo.toml --tests + - cargo test --manifest-path rand_core/Cargo.toml --no-default-features --tests - cargo test --manifest-path rand_isaac/Cargo.toml --features=serde1 # TODO: cannot test rand_pcg due to explicit dependency on i128 - cargo test --manifest-path rand_xorshift/Cargo.toml --features=serde1 @@ -88,8 +88,8 @@ matrix: # TODO: add simd_support feature: - cargo test --features=serde1,log - cargo test --examples - - cargo test --manifest-path rand_core/Cargo.toml - - cargo test --manifest-path rand_core/Cargo.toml --no-default-features + - cargo test --manifest-path rand_core/Cargo.toml --tests + - cargo test --manifest-path rand_core/Cargo.toml --no-default-features --tests - cargo test --manifest-path rand_isaac/Cargo.toml --features=serde1 - cargo test --manifest-path rand_pcg/Cargo.toml --features=serde1 - cargo test --manifest-path rand_xorshift/Cargo.toml --features=serde1 @@ -116,8 +116,8 @@ matrix: - cargo test --all-features - cargo test --benches --features=nightly - cargo test --examples - - cargo test --manifest-path rand_core/Cargo.toml - - cargo test --manifest-path rand_core/Cargo.toml --no-default-features --features=alloc + - cargo test --manifest-path rand_core/Cargo.toml --tests + - cargo test --manifest-path rand_core/Cargo.toml --no-default-features --features=alloc --tests - cargo test --manifest-path rand_isaac/Cargo.toml --features=serde1 - cargo test --manifest-path rand_pcg/Cargo.toml --features=serde1 - cargo test --manifest-path rand_xorshift/Cargo.toml --features=serde1 @@ -209,8 +209,8 @@ script: # TODO: add simd_support feature: - cargo test --features=serde1,log - cargo test --examples - - cargo test --manifest-path rand_core/Cargo.toml - - cargo test --manifest-path rand_core/Cargo.toml --no-default-features + - cargo test --manifest-path rand_core/Cargo.toml --tests + - cargo test --manifest-path rand_core/Cargo.toml --no-default-features --tests - cargo test --manifest-path rand_isaac/Cargo.toml --features=serde1 - cargo test --manifest-path rand_pcg/Cargo.toml --features=serde1 - cargo test --manifest-path rand_xorshift/Cargo.toml --features=serde1 diff --git a/Cargo.toml b/Cargo.toml index ccdc008cec7..7013f8c226b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,6 +82,3 @@ autocfg = "0.1" [package.metadata.docs.rs] all-features = true - -[patch.crates-io] -rand_core = { path = "rand_core", version = "0.4" } diff --git a/appveyor.yml b/appveyor.yml index 70a8cada336..0c72a273d5c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -37,8 +37,8 @@ test_script: - cargo test --features=serde1,log - cargo test --benches --features=nightly - cargo test --examples - - cargo test --manifest-path rand_core/Cargo.toml - - cargo test --manifest-path rand_core/Cargo.toml --no-default-features --features=alloc + - cargo test --manifest-path rand_core/Cargo.toml --tests + - cargo test --manifest-path rand_core/Cargo.toml --no-default-features --features=alloc --tests - cargo test --manifest-path rand_isaac/Cargo.toml --features=serde1 - cargo test --manifest-path rand_pcg/Cargo.toml --features=serde1 - cargo test --manifest-path rand_xorshift/Cargo.toml --features=serde1 diff --git a/rand_core/CHANGELOG.md b/rand_core/CHANGELOG.md index 7f2d7978fdc..c2b5fa81be8 100644 --- a/rand_core/CHANGELOG.md +++ b/rand_core/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.4.2] - 2019-06-?? +- Compatibility shim around version 0.5 + ## [0.4.0] - 2019-01-24 - Disable the `std` feature by default (#702) diff --git a/rand_core/Cargo.toml b/rand_core/Cargo.toml index 340fb3a40a5..ad296bb30ff 100644 --- a/rand_core/Cargo.toml +++ b/rand_core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rand_core" -version = "0.4.0" +version = "0.4.2" authors = ["The Rand Project Developers", "The Rust Project Developers"] license = "MIT/Apache-2.0" readme = "README.md" @@ -18,10 +18,9 @@ travis-ci = { repository = "rust-random/rand" } appveyor = { repository = "rust-random/rand" } [features] -std = ["alloc"] # use std library; should be default but for above bug -alloc = [] # enables Vec and Box support without std -serde1 = ["serde", "serde_derive"] # enables serde for BlockRng wrapper +std = ["rand_core/std"] # use std library; should be default but for above bug +alloc = ["rand_core/alloc"] # enables Vec and Box support without std +serde1 = ["rand_core/serde1"] # enables serde for BlockRng wrapper [dependencies] -serde = { version = "1", optional = true } -serde_derive = { version = "^1.0.38", optional = true } +rand_core = { version = "0.5" } diff --git a/rand_core/src/block.rs b/rand_core/src/block.rs deleted file mode 100644 index 3045b9482f4..00000000000 --- a/rand_core/src/block.rs +++ /dev/null @@ -1,499 +0,0 @@ -// Copyright 2018 Developers of the Rand project. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! The `BlockRngCore` trait and implementation helpers -//! -//! The [`BlockRngCore`] trait exists to assist in the implementation of RNGs -//! which generate a block of data in a cache instead of returning generated -//! values directly. -//! -//! Usage of this trait is optional, but provides two advantages: -//! implementations only need to concern themselves with generation of the -//! block, not the various [`RngCore`] methods (especially [`fill_bytes`], where -//! the optimal implementations are not trivial), and this allows -//! `ReseedingRng` (see [`rand`](https://docs.rs/rand) crate) perform periodic -//! reseeding with very low overhead. -//! -//! # Example -//! -//! ```norun -//! use rand_core::block::{BlockRngCore, BlockRng}; -//! -//! struct MyRngCore; -//! -//! impl BlockRngCore for MyRngCore { -//! type Results = [u32; 16]; -//! -//! fn generate(&mut self, results: &mut Self::Results) { -//! unimplemented!() -//! } -//! } -//! -//! impl SeedableRng for MyRngCore { -//! type Seed = unimplemented!(); -//! fn from_seed(seed: Self::Seed) -> Self { -//! unimplemented!() -//! } -//! } -//! -//! // optionally, also implement CryptoRng for MyRngCore -//! -//! // Final RNG. -//! type MyRng = BlockRng; -//! ``` -//! -//! [`BlockRngCore`]: crate::block::BlockRngCore -//! [`fill_bytes`]: RngCore::fill_bytes - -use core::convert::AsRef; -use core::fmt; -use {RngCore, CryptoRng, SeedableRng, Error}; -use impls::{fill_via_u32_chunks, fill_via_u64_chunks}; - -/// A trait for RNGs which do not generate random numbers individually, but in -/// blocks (typically `[u32; N]`). This technique is commonly used by -/// cryptographic RNGs to improve performance. -/// -/// See the [module][crate::block] documentation for details. -pub trait BlockRngCore { - /// Results element type, e.g. `u32`. - type Item; - - /// Results type. This is the 'block' an RNG implementing `BlockRngCore` - /// generates, which will usually be an array like `[u32; 16]`. - type Results: AsRef<[Self::Item]> + AsMut<[Self::Item]> + Default; - - /// Generate a new block of results. - fn generate(&mut self, results: &mut Self::Results); -} - - -/// A wrapper type implementing [`RngCore`] for some type implementing -/// [`BlockRngCore`] with `u32` array buffer; i.e. this can be used to implement -/// a full RNG from just a `generate` function. -/// -/// The `core` field may be accessed directly but the results buffer may not. -/// PRNG implementations can simply use a type alias -/// (`pub type MyRng = BlockRng;`) but might prefer to use a -/// wrapper type (`pub struct MyRng(BlockRng);`); the latter must -/// re-implement `RngCore` but hides the implementation details and allows -/// extra functionality to be defined on the RNG -/// (e.g. `impl MyRng { fn set_stream(...){...} }`). -/// -/// `BlockRng` has heavily optimized implementations of the [`RngCore`] methods -/// reading values from the results buffer, as well as -/// calling [`BlockRngCore::generate`] directly on the output array when -/// [`fill_bytes`] / [`try_fill_bytes`] is called on a large array. These methods -/// also handle the bookkeeping of when to generate a new batch of values. -/// -/// No whole generated `u32` values are thown away and all values are consumed -/// in-order. [`next_u32`] simply takes the next available `u32` value. -/// [`next_u64`] is implemented by combining two `u32` values, least -/// significant first. [`fill_bytes`] and [`try_fill_bytes`] consume a whole -/// number of `u32` values, converting each `u32` to a byte slice in -/// little-endian order. If the requested byte length is not a multiple of 4, -/// some bytes will be discarded. -/// -/// See also [`BlockRng64`] which uses `u64` array buffers. Currently there is -/// no direct support for other buffer types. -/// -/// For easy initialization `BlockRng` also implements [`SeedableRng`]. -/// -/// [`next_u32`]: RngCore::next_u32 -/// [`next_u64`]: RngCore::next_u64 -/// [`fill_bytes`]: RngCore::fill_bytes -/// [`try_fill_bytes`]: RngCore::try_fill_bytes -#[derive(Clone)] -#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))] -pub struct BlockRng { - results: R::Results, - index: usize, - /// The *core* part of the RNG, implementing the `generate` function. - pub core: R, -} - -// Custom Debug implementation that does not expose the contents of `results`. -impl fmt::Debug for BlockRng { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("BlockRng") - .field("core", &self.core) - .field("result_len", &self.results.as_ref().len()) - .field("index", &self.index) - .finish() - } -} - -impl BlockRng { - /// Create a new `BlockRng` from an existing RNG implementing - /// `BlockRngCore`. Results will be generated on first use. - pub fn new(core: R) -> BlockRng{ - let results_empty = R::Results::default(); - BlockRng { - core, - index: results_empty.as_ref().len(), - results: results_empty, - } - } - - /// Get the index into the result buffer. - /// - /// If this is equal to or larger than the size of the result buffer then - /// the buffer is "empty" and `generate()` must be called to produce new - /// results. - pub fn index(&self) -> usize { - self.index - } - - /// Reset the number of available results. - /// This will force a new set of results to be generated on next use. - pub fn reset(&mut self) { - self.index = self.results.as_ref().len(); - } - - /// Generate a new set of results immediately, setting the index to the - /// given value. - pub fn generate_and_set(&mut self, index: usize) { - assert!(index < self.results.as_ref().len()); - self.core.generate(&mut self.results); - self.index = index; - } -} - -impl> RngCore for BlockRng -where ::Results: AsRef<[u32]> + AsMut<[u32]> -{ - #[inline(always)] - fn next_u32(&mut self) -> u32 { - if self.index >= self.results.as_ref().len() { - self.generate_and_set(0); - } - - let value = self.results.as_ref()[self.index]; - self.index += 1; - value - } - - #[inline(always)] - fn next_u64(&mut self) -> u64 { - let read_u64 = |results: &[u32], index| { - if cfg!(any(target_arch = "x86", target_arch = "x86_64")) { - // requires little-endian CPU supporting unaligned reads: - unsafe { *(&results[index] as *const u32 as *const u64) } - } else { - let x = u64::from(results[index]); - let y = u64::from(results[index + 1]); - (y << 32) | x - } - }; - - let len = self.results.as_ref().len(); - - let index = self.index; - if index < len-1 { - self.index += 2; - // Read an u64 from the current index - read_u64(self.results.as_ref(), index) - } else if index >= len { - self.generate_and_set(2); - read_u64(self.results.as_ref(), 0) - } else { - let x = u64::from(self.results.as_ref()[len-1]); - self.generate_and_set(1); - let y = u64::from(self.results.as_ref()[0]); - (y << 32) | x - } - } - - // As an optimization we try to write directly into the output buffer. - // This is only enabled for little-endian platforms where unaligned writes - // are known to be safe and fast. - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - fn fill_bytes(&mut self, dest: &mut [u8]) { - let mut filled = 0; - - // Continue filling from the current set of results - if self.index < self.results.as_ref().len() { - let (consumed_u32, filled_u8) = - fill_via_u32_chunks(&self.results.as_ref()[self.index..], - dest); - - self.index += consumed_u32; - filled += filled_u8; - } - - let len_remainder = - (dest.len() - filled) % (self.results.as_ref().len() * 4); - let end_direct = dest.len() - len_remainder; - - while filled < end_direct { - let dest_u32: &mut R::Results = unsafe { - &mut *(dest[filled..].as_mut_ptr() as - *mut ::Results) - }; - self.core.generate(dest_u32); - filled += self.results.as_ref().len() * 4; - self.index = self.results.as_ref().len(); - } - - if len_remainder > 0 { - self.core.generate(&mut self.results); - let (consumed_u32, _) = - fill_via_u32_chunks(self.results.as_ref(), - &mut dest[filled..]); - - self.index = consumed_u32; - } - } - - #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] - fn fill_bytes(&mut self, dest: &mut [u8]) { - let mut read_len = 0; - while read_len < dest.len() { - if self.index >= self.results.as_ref().len() { - self.generate_and_set(0); - } - let (consumed_u32, filled_u8) = - fill_via_u32_chunks(&self.results.as_ref()[self.index..], - &mut dest[read_len..]); - - self.index += consumed_u32; - read_len += filled_u8; - } - } - - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { - self.fill_bytes(dest); - Ok(()) - } -} - -impl SeedableRng for BlockRng { - type Seed = R::Seed; - - fn from_seed(seed: Self::Seed) -> Self { - Self::new(R::from_seed(seed)) - } - - fn seed_from_u64(seed: u64) -> Self { - Self::new(R::seed_from_u64(seed)) - } - - fn from_rng(rng: S) -> Result { - Ok(Self::new(R::from_rng(rng)?)) - } -} - - - -/// A wrapper type implementing [`RngCore`] for some type implementing -/// [`BlockRngCore`] with `u64` array buffer; i.e. this can be used to implement -/// a full RNG from just a `generate` function. -/// -/// This is similar to [`BlockRng`], but specialized for algorithms that operate -/// on `u64` values. -/// -/// No whole generated `u64` values are thrown away and all values are consumed -/// in-order. [`next_u64`] simply takes the next available `u64` value. -/// [`next_u32`] is however a bit special: half of a `u64` is consumed, leaving -/// the other half in the buffer. If the next function called is [`next_u32`] -/// then the other half is then consumed, however both [`next_u64`] and -/// [`fill_bytes`] discard the rest of any half-consumed `u64`s when called. -/// -/// [`fill_bytes`] and [`try_fill_bytes`] consume a whole number of `u64` -/// values. If the requested length is not a multiple of 8, some bytes will be -/// discarded. -/// -/// [`next_u32`]: RngCore::next_u32 -/// [`next_u64`]: RngCore::next_u64 -/// [`fill_bytes`]: RngCore::fill_bytes -/// [`try_fill_bytes`]: RngCore::try_fill_bytes -#[derive(Clone)] -#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))] -pub struct BlockRng64 { - results: R::Results, - index: usize, - half_used: bool, // true if only half of the previous result is used - /// The *core* part of the RNG, implementing the `generate` function. - pub core: R, -} - -// Custom Debug implementation that does not expose the contents of `results`. -impl fmt::Debug for BlockRng64 { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("BlockRng64") - .field("core", &self.core) - .field("result_len", &self.results.as_ref().len()) - .field("index", &self.index) - .field("half_used", &self.half_used) - .finish() - } -} - -impl BlockRng64 { - /// Create a new `BlockRng` from an existing RNG implementing - /// `BlockRngCore`. Results will be generated on first use. - pub fn new(core: R) -> BlockRng64{ - let results_empty = R::Results::default(); - BlockRng64 { - core, - index: results_empty.as_ref().len(), - half_used: false, - results: results_empty, - } - } - - /// Get the index into the result buffer. - /// - /// If this is equal to or larger than the size of the result buffer then - /// the buffer is "empty" and `generate()` must be called to produce new - /// results. - pub fn index(&self) -> usize { - self.index - } - - /// Reset the number of available results. - /// This will force a new set of results to be generated on next use. - pub fn reset(&mut self) { - self.index = self.results.as_ref().len(); - self.half_used = false; - } - - /// Generate a new set of results immediately, setting the index to the - /// given value. - pub fn generate_and_set(&mut self, index: usize) { - assert!(index < self.results.as_ref().len()); - self.core.generate(&mut self.results); - self.index = index; - self.half_used = false; - } -} - -impl> RngCore for BlockRng64 -where ::Results: AsRef<[u64]> + AsMut<[u64]> -{ - #[inline(always)] - fn next_u32(&mut self) -> u32 { - let mut index = self.index * 2 - self.half_used as usize; - if index >= self.results.as_ref().len() * 2 { - self.core.generate(&mut self.results); - self.index = 0; - // `self.half_used` is by definition `false` - self.half_used = false; - index = 0; - } - - self.half_used = !self.half_used; - self.index += self.half_used as usize; - - // Index as if this is a u32 slice. - unsafe { - let results = - &*(self.results.as_ref() as *const [u64] as *const [u32]); - if cfg!(target_endian = "little") { - *results.get_unchecked(index) - } else { - *results.get_unchecked(index ^ 1) - } - } - } - - #[inline(always)] - fn next_u64(&mut self) -> u64 { - if self.index >= self.results.as_ref().len() { - self.core.generate(&mut self.results); - self.index = 0; - } - - let value = self.results.as_ref()[self.index]; - self.index += 1; - self.half_used = false; - value - } - - // As an optimization we try to write directly into the output buffer. - // This is only enabled for little-endian platforms where unaligned writes - // are known to be safe and fast. - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - fn fill_bytes(&mut self, dest: &mut [u8]) { - let mut filled = 0; - self.half_used = false; - - // Continue filling from the current set of results - if self.index < self.results.as_ref().len() { - let (consumed_u64, filled_u8) = - fill_via_u64_chunks(&self.results.as_ref()[self.index..], - dest); - - self.index += consumed_u64; - filled += filled_u8; - } - - let len_remainder = - (dest.len() - filled) % (self.results.as_ref().len() * 8); - let end_direct = dest.len() - len_remainder; - - while filled < end_direct { - let dest_u64: &mut R::Results = unsafe { - ::core::mem::transmute(dest[filled..].as_mut_ptr()) - }; - self.core.generate(dest_u64); - filled += self.results.as_ref().len() * 8; - self.index = self.results.as_ref().len(); - } - - if len_remainder > 0 { - self.core.generate(&mut self.results); - let (consumed_u64, _) = - fill_via_u64_chunks(&mut self.results.as_ref(), - &mut dest[filled..]); - - self.index = consumed_u64; - } - } - - #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] - fn fill_bytes(&mut self, dest: &mut [u8]) { - let mut read_len = 0; - self.half_used = false; - while read_len < dest.len() { - if self.index as usize >= self.results.as_ref().len() { - self.core.generate(&mut self.results); - self.index = 0; - } - - let (consumed_u64, filled_u8) = - fill_via_u64_chunks(&self.results.as_ref()[self.index as usize..], - &mut dest[read_len..]); - - self.index += consumed_u64; - read_len += filled_u8; - } - } - - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { - Ok(self.fill_bytes(dest)) - } -} - -impl SeedableRng for BlockRng64 { - type Seed = R::Seed; - - fn from_seed(seed: Self::Seed) -> Self { - Self::new(R::from_seed(seed)) - } - - fn seed_from_u64(seed: u64) -> Self { - Self::new(R::seed_from_u64(seed)) - } - - fn from_rng(rng: S) -> Result { - Ok(Self::new(R::from_rng(rng)?)) - } -} - -impl CryptoRng for BlockRng {} diff --git a/rand_core/src/error.rs b/rand_core/src/error.rs index 5a8459ea8be..0e2ef82e94f 100644 --- a/rand_core/src/error.rs +++ b/rand_core/src/error.rs @@ -15,6 +15,8 @@ use std::error::Error as stdError; #[cfg(feature="std")] use std::io; +use core5::Error as Error5; + /// Error kind which can be matched over. #[derive(PartialEq, Eq, Debug, Copy, Clone)] pub enum ErrorKind { @@ -175,3 +177,33 @@ impl From for io::Error { } } } + +impl From for Error { + fn from(_error: Error5) -> Self { + #[cfg(feature="std")] { + Error::with_cause( + ErrorKind::Unavailable, + "(from rand_core5::Error)", + _error.take_inner() + ) + } + #[cfg(not(feature="std"))] { + Error::new( + ErrorKind::Unavailable, + "(from rand_core5::Error)" + ) + } + } +} + +impl From for Error5 { + fn from(_error: Error) -> Self { + #[cfg(feature="std")] { + Error5::new(Box::new(_error)) + } + #[cfg(not(feature="std"))] { + use core::num::NonZeroU32; + Error5::from(NonZeroU32::new(1897042795).unwrap()) + } + } +} diff --git a/rand_core/src/le.rs b/rand_core/src/le.rs deleted file mode 100644 index 266651f10dc..00000000000 --- a/rand_core/src/le.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2018 Developers of the Rand project. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Little-Endian utilities -//! -//! Little-Endian order has been chosen for internal usage; this makes some -//! useful functions available. - -use core::ptr; - -macro_rules! read_slice { - ($src:expr, $dst:expr, $size:expr, $which:ident) => {{ - assert_eq!($src.len(), $size * $dst.len()); - - unsafe { - ptr::copy_nonoverlapping( - $src.as_ptr(), - $dst.as_mut_ptr() as *mut u8, - $src.len()); - } - for v in $dst.iter_mut() { - *v = v.$which(); - } - }}; -} - -/// Reads unsigned 32 bit integers from `src` into `dst`. -/// Borrowed from the `byteorder` crate. -#[inline] -pub fn read_u32_into(src: &[u8], dst: &mut [u32]) { - read_slice!(src, dst, 4, to_le); -} - -/// Reads unsigned 64 bit integers from `src` into `dst`. -/// Borrowed from the `byteorder` crate. -#[inline] -pub fn read_u64_into(src: &[u8], dst: &mut [u64]) { - read_slice!(src, dst, 8, to_le); -} - -#[test] -fn test_read() { - let bytes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - - let mut buf = [0u32; 4]; - read_u32_into(&bytes, &mut buf); - assert_eq!(buf[0], 0x04030201); - assert_eq!(buf[3], 0x100F0E0D); - - let mut buf = [0u32; 3]; - read_u32_into(&bytes[1..13], &mut buf); // unaligned - assert_eq!(buf[0], 0x05040302); - assert_eq!(buf[2], 0x0D0C0B0A); - - let mut buf = [0u64; 2]; - read_u64_into(&bytes, &mut buf); - assert_eq!(buf[0], 0x0807060504030201); - assert_eq!(buf[1], 0x100F0E0D0C0B0A09); - - let mut buf = [0u64; 1]; - read_u64_into(&bytes[7..15], &mut buf); // unaligned - assert_eq!(buf[0], 0x0F0E0D0C0B0A0908); -} diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index 4b0e6e48b01..0cd24d2aed9 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -42,6 +42,7 @@ #[cfg(all(feature = "alloc", not(feature="std")))] extern crate alloc; #[cfg(feature="serde1")] extern crate serde; #[cfg(feature="serde1")] #[macro_use] extern crate serde_derive; +extern crate rand_core as core5; use core::default::Default; @@ -51,12 +52,10 @@ use core::ptr::copy_nonoverlapping; #[cfg(all(feature="alloc", not(feature="std")))] use alloc::boxed::Box; pub use error::{ErrorKind, Error}; - +pub use core5::{block, le, CryptoRng}; mod error; -pub mod block; pub mod impls; -pub mod le; /// The core of a random number generator. @@ -184,30 +183,6 @@ pub trait RngCore { fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error>; } -/// A marker trait used to indicate that an [`RngCore`] or [`BlockRngCore`] -/// implementation is supposed to be cryptographically secure. -/// -/// *Cryptographically secure generators*, also known as *CSPRNGs*, should -/// satisfy an additional properties over other generators: given the first -/// *k* bits of an algorithm's output -/// sequence, it should not be possible using polynomial-time algorithms to -/// predict the next bit with probability significantly greater than 50%. -/// -/// Some generators may satisfy an additional property, however this is not -/// required by this trait: if the CSPRNG's state is revealed, it should not be -/// computationally-feasible to reconstruct output prior to this. Some other -/// generators allow backwards-computation and are consided *reversible*. -/// -/// Note that this trait is provided for guidance only and cannot guarantee -/// suitability for cryptographic applications. In general it should only be -/// implemented for well-reviewed code implementing well-regarded algorithms. -/// -/// Note also that use of a `CryptoRng` does not protect against other -/// weaknesses such as seeding from a weak entropy source or leaking state. -/// -/// [`BlockRngCore`]: block::BlockRngCore -pub trait CryptoRng {} - /// A random number generator that can be explicitly seeded. /// /// This trait encapsulates the low-level functionality common to all @@ -426,12 +401,70 @@ impl std::io::Read for RngCore { } } -// Implement `CryptoRng` for references to an `CryptoRng`. -impl<'a, R: CryptoRng + ?Sized> CryptoRng for &'a mut R {} - -// Implement `CryptoRng` for boxed references to an `CryptoRng`. -#[cfg(feature="alloc")] -impl CryptoRng for Box {} +mod compat { + use super::*; + + /// A wrapper type which allows any type implementing `RngCore` from version + /// 0.4.0 to support `RngCore` from version 0.5.0. + pub struct FutureRngCore(pub R); + impl core5::RngCore for FutureRngCore { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.next_u32() + } + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.next_u64() + } + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.fill_bytes(dest) + } + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.try_fill_bytes(dest) + .map_err(|e| Error::from(e)) + } + } + + impl RngCore for T { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + core5::RngCore::next_u32(self) + } + #[inline(always)] + fn next_u64(&mut self) -> u64 { + core5::RngCore::next_u64(self) + } + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + core5::RngCore::fill_bytes(self, dest) + } + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + core5::RngCore::try_fill_bytes(self, dest) + .map_err(|e| Error::from(e)) + } + } + + impl SeedableRng for T { + type Seed = ::Seed; + #[inline(always)] + fn from_seed(seed: Self::Seed) -> Self { + core5::SeedableRng::from_seed(seed) + } + #[inline(always)] + fn seed_from_u64(mut state: u64) -> Self { + core5::SeedableRng::seed_from_u64(state) + } + #[inline(always)] + fn from_rng(mut rng: R) -> Result { + let rng = FutureRngCore(rng); + core5::SeedableRng::from_rng(rng) + .map_err(|e| Error::from(e)) + } + } +} #[cfg(test)] mod test { diff --git a/utils/ci/script.sh b/utils/ci/script.sh index d6338cce2fe..a5904b6f5fa 100644 --- a/utils/ci/script.sh +++ b/utils/ci/script.sh @@ -7,8 +7,8 @@ main() { # TODO: add simd_support feature: cross test --target $TARGET --features=serde1,log cross test --target $TARGET --examples - cross test --target $TARGET --manifest-path rand_core/Cargo.toml - cross test --target $TARGET --manifest-path rand_core/Cargo.toml --no-default-features + cross test --target $TARGET --manifest-path rand_core/Cargo.toml --tests + cross test --target $TARGET --manifest-path rand_core/Cargo.toml --no-default-features --tests cross test --target $TARGET --manifest-path rand_isaac/Cargo.toml --features=serde1 cross test --target $TARGET --manifest-path rand_pcg/Cargo.toml --features=serde1 cross test --target $TARGET --manifest-path rand_xorshift/Cargo.toml --features=serde1