aboutsummaryrefslogtreecommitdiff
path: root/rand/rand_core
diff options
context:
space:
mode:
Diffstat (limited to 'rand/rand_core')
-rw-r--r--rand/rand_core/CHANGELOG.md31
-rw-r--r--rand/rand_core/Cargo.toml16
-rw-r--r--rand/rand_core/README.md31
-rw-r--r--rand/rand_core/src/block.rs185
-rw-r--r--rand/rand_core/src/error.rs267
-rw-r--r--rand/rand_core/src/impls.rs15
-rw-r--r--rand/rand_core/src/lib.rs246
-rw-r--r--rand/rand_core/src/os.rs85
8 files changed, 472 insertions, 404 deletions
diff --git a/rand/rand_core/CHANGELOG.md b/rand/rand_core/CHANGELOG.md
index 2cbb259..dfdd692 100644
--- a/rand/rand_core/CHANGELOG.md
+++ b/rand/rand_core/CHANGELOG.md
@@ -4,30 +4,55 @@ 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.5.1] - 2019-08-28
+- `OsRng` added to `rand_core` (#863)
+- `Error::INTERNAL_START` and `Error::CUSTOM_START` constants (#864)
+- `Error::raw_os_error` method (#864)
+- `Debug` and `Display` formatting for `getrandom` error codes without `std` (#864)
+### Changed
+- `alloc` feature in `no_std` is available since Rust 1.36 (#856)
+- Added `#[inline]` to `Error` conversion methods (#864)
+
+## [0.5.0] - 2019-06-06
+### Changed
+- Enable testing with Miri and fix incorrect pointer usages (#779, #780, #781, #783, #784)
+- Rewrite `Error` type and adjust API (#800)
+- Adjust usage of `#[inline]` for `BlockRng` and `BlockRng64`
+
+## [0.4.0] - 2019-01-24
+### Changed
+- Disable the `std` feature by default (#702)
+
## [0.3.0] - 2018-09-24
+### Added
- Add `SeedableRng::seed_from_u64` for convenient seeding. (#537)
## [0.2.1] - 2018-06-08
+### Added
- References to a `CryptoRng` now also implement `CryptoRng`. (#470)
## [0.2.0] - 2018-05-21
+### Changed
- Enable the `std` feature by default. (#409)
- Remove `BlockRng{64}::inner` and `BlockRng::inner_mut`; instead making `core` public
-- Add `BlockRng{64}::index` and `BlockRng{64}::generate_and_set`. (#374, #419)
- Change `BlockRngCore::Results` bound to also require `AsMut<[Self::Item]>`. (#419)
+### Added
+- Add `BlockRng{64}::index` and `BlockRng{64}::generate_and_set`. (#374, #419)
- Implement `std::io::Read` for RngCore. (#434)
## [0.1.0] - 2018-04-17
-(Split out of the Rand crate, changes here are relative to rand 0.4.2)
+(Split out of the Rand crate, changes here are relative to rand 0.4.2.)
+### Added
- `RngCore` and `SeedableRng` are now part of `rand_core`. (#288)
- Add modules to help implementing RNGs `impl` and `le`. (#209, #228)
- Add `Error` and `ErrorKind`. (#225)
- Add `CryptoRng` marker trait. (#273)
- Add `BlockRngCore` trait. (#281)
- Add `BlockRng` and `BlockRng64` wrappers to help implementations. (#281, #325)
+- Add `RngCore::try_fill_bytes`. (#225)
+### Changed
- Revise the `SeedableRng` trait. (#233)
- Remove default implementations for `RngCore::next_u64` and `RngCore::fill_bytes`. (#288)
-- Add `RngCore::try_fill_bytes`. (#225)
## [0.0.1] - 2017-09-14 (yanked)
Experimental version as part of the rand crate refactor.
diff --git a/rand/rand_core/Cargo.toml b/rand/rand_core/Cargo.toml
index 1678773..e52af5f 100644
--- a/rand/rand_core/Cargo.toml
+++ b/rand/rand_core/Cargo.toml
@@ -1,28 +1,28 @@
[package]
name = "rand_core"
-version = "0.3.0"
+version = "0.5.1"
authors = ["The Rand Project Developers", "The Rust Project Developers"]
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
readme = "README.md"
repository = "https://github.com/rust-random/rand"
-documentation = "https://rust-random.github.io/rand/rand_core"
+documentation = "https://rust-random.github.io/rand/rand_core/"
homepage = "https://crates.io/crates/rand_core"
description = """
Core random number generator traits and tools for implementation.
"""
keywords = ["random", "rng"]
categories = ["algorithms", "no-std"]
+edition = "2018"
[badges]
travis-ci = { repository = "rust-random/rand" }
appveyor = { repository = "rust-random/rand" }
[features]
-default = ["std"]
-std = ["alloc"] # use std library; should be default but for above bug
+std = ["alloc", "getrandom", "getrandom/std"] # 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
+serde1 = ["serde"] # enables serde for BlockRng wrapper
[dependencies]
-serde = { version = "1", optional = true }
-serde_derive = { version = "^1.0.38", optional = true }
+serde = { version = "1", features = ["derive"], optional = true }
+getrandom = { version = "0.1", optional = true }
diff --git a/rand/rand_core/README.md b/rand/rand_core/README.md
index dee6504..467e66f 100644
--- a/rand/rand_core/README.md
+++ b/rand/rand_core/README.md
@@ -6,7 +6,7 @@
[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/)
[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_core)
[![API](https://docs.rs/rand_core/badge.svg)](https://docs.rs/rand_core)
-[![Minimum rustc version](https://img.shields.io/badge/rustc-1.22+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)
+[![Minimum rustc version](https://img.shields.io/badge/rustc-1.32+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)
Core traits and error types of the [rand] library, plus tools for implementing
RNGs.
@@ -25,7 +25,7 @@ Links:
- [API documentation (master)](https://rust-random.github.io/rand/rand_core)
- [API documentation (docs.rs)](https://docs.rs/rand_core)
-- [Changelog](CHANGELOG.md)
+- [Changelog](https://github.com/rust-random/rand/blob/master/rand_core/CHANGELOG.md)
[rand]: https://crates.io/crates/rand
@@ -40,17 +40,34 @@ The `rand_core` crate provides:
The traits and error types are also available via `rand`.
+## Versions
+
+The current version is:
+```
+rand_core = "0.5.0"
+```
+
+Rand libs have inter-dependencies and make use of the
+[semver trick](https://github.com/dtolnay/semver-trick/) in order to make traits
+compatible across crate versions. (This is especially important for `RngCore`
+and `SeedableRng`.) A few crate releases are thus compatibility shims,
+depending on the *next* lib version (e.g. `rand_core` versions `0.2.2` and
+`0.3.1`). This means, for example, that `rand_core_0_4_0::SeedableRng` and
+`rand_core_0_3_0::SeedableRng` are distinct, incompatible traits, which can
+cause build errors. Usually, running `cargo update` is enough to fix any issues.
+
## Crate Features
`rand_core` supports `no_std` and `alloc`-only configurations, as well as full
`std` functionality. The differences between `no_std` and full `std` are small,
-comprising `RngCore` support for `Box<R>` types where `R: RngCore`, as well as
+comprising `RngCore` support for `Box<R>` types where `R: RngCore`,
+`std::io::Read` support for types supporting `RngCore`, and
extensions to the `Error` type's functionality.
-Due to [rust-lang/cargo#1596](https://github.com/rust-lang/cargo/issues/1596),
-`rand_core` is built without `std` support by default. Since features are
-unioned across the whole dependency tree, any crate using `rand` with its
-default features will also enable `std` support in `rand_core`.
+The `std` feature is *not enabled by default*. This is primarily to avoid build
+problems where one crate implicitly requires `rand_core` with `std` support and
+another crate requires `rand` *without* `std` support. However, the `rand` crate
+continues to enable `std` support by default, both for itself and `rand_core`.
The `serde1` feature can be used to derive `Serialize` and `Deserialize` for RNG
implementations that use the `BlockRng` or `BlockRng64` wrappers.
diff --git a/rand/rand_core/src/block.rs b/rand/rand_core/src/block.rs
index de480e4..0ab7458 100644
--- a/rand/rand_core/src/block.rs
+++ b/rand/rand_core/src/block.rs
@@ -16,55 +16,55 @@
//! 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`] perform periodic reseeding with very low overhead.
+//! `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<u32, MyRngCore>;
//! ```
-//!
-//! [`BlockRngCore`]: trait.BlockRngCore.html
-//! [`RngCore`]: ../trait.RngCore.html
-//! [`fill_bytes`]: ../trait.RngCore.html#tymethod.fill_bytes
-//! [`ReseedingRng`]: ../../rand/rngs/adapter/struct.ReseedingRng.html
+//!
+//! [`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};
+use core::{fmt, ptr};
+#[cfg(feature="serde1")] use serde::{Serialize, Deserialize};
+use crate::{RngCore, CryptoRng, SeedableRng, Error};
+use crate::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 documentation](index.html) for details.
+///
+/// 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;
@@ -105,15 +105,10 @@ pub trait BlockRngCore {
///
/// For easy initialization `BlockRng` also implements [`SeedableRng`].
///
-/// [`BlockRngCore`]: BlockRngCore.t.html
-/// [`BlockRngCore::generate`]: trait.BlockRngCore.html#tymethod.generate
-/// [`BlockRng64`]: struct.BlockRng64.html
-/// [`RngCore`]: ../RngCore.t.html
-/// [`next_u32`]: ../trait.RngCore.html#tymethod.next_u32
-/// [`next_u64`]: ../trait.RngCore.html#tymethod.next_u64
-/// [`fill_bytes`]: ../trait.RngCore.html#tymethod.fill_bytes
-/// [`try_fill_bytes`]: ../trait.RngCore.html#tymethod.try_fill_bytes
-/// [`SeedableRng`]: ../SeedableRng.t.html
+/// [`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<R: BlockRngCore + ?Sized> {
@@ -137,6 +132,7 @@ impl<R: BlockRngCore + fmt::Debug> fmt::Debug for BlockRng<R> {
impl<R: BlockRngCore> BlockRng<R> {
/// Create a new `BlockRng` from an existing RNG implementing
/// `BlockRngCore`. Results will be generated on first use.
+ #[inline]
pub fn new(core: R) -> BlockRng<R>{
let results_empty = R::Results::default();
BlockRng {
@@ -147,22 +143,25 @@ impl<R: BlockRngCore> BlockRng<R> {
}
/// 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.
+ #[inline(always)]
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.
+ #[inline]
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.
+ #[inline]
pub fn generate_and_set(&mut self, index: usize) {
assert!(index < self.results.as_ref().len());
self.core.generate(&mut self.results);
@@ -173,7 +172,7 @@ impl<R: BlockRngCore> BlockRng<R> {
impl<R: BlockRngCore<Item=u32>> RngCore for BlockRng<R>
where <R as BlockRngCore>::Results: AsRef<[u32]> + AsMut<[u32]>
{
- #[inline(always)]
+ #[inline]
fn next_u32(&mut self) -> u32 {
if self.index >= self.results.as_ref().len() {
self.generate_and_set(0);
@@ -184,12 +183,14 @@ where <R as BlockRngCore>::Results: AsRef<[u32]> + AsMut<[u32]>
value
}
- #[inline(always)]
+ #[inline]
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) }
+ if cfg!(any(target_endian = "little")) {
+ // requires little-endian CPU
+ #[allow(clippy::cast_ptr_alignment)] // false positive
+ let ptr: *const u64 = results[index..=index+1].as_ptr() as *const u64;
+ unsafe { ptr::read_unaligned(ptr) }
} else {
let x = u64::from(results[index]);
let y = u64::from(results[index + 1]);
@@ -215,48 +216,7 @@ where <R as BlockRngCore>::Results: AsRef<[u32]> + AsMut<[u32]>
}
}
- // 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 <R as BlockRngCore>::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")))]
+ #[inline]
fn fill_bytes(&mut self, dest: &mut [u8]) {
let mut read_len = 0;
while read_len < dest.len() {
@@ -272,6 +232,7 @@ where <R as BlockRngCore>::Results: AsRef<[u32]> + AsMut<[u32]>
}
}
+ #[inline(always)]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
self.fill_bytes(dest);
Ok(())
@@ -281,14 +242,17 @@ where <R as BlockRngCore>::Results: AsRef<[u32]> + AsMut<[u32]>
impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {
type Seed = R::Seed;
+ #[inline(always)]
fn from_seed(seed: Self::Seed) -> Self {
Self::new(R::from_seed(seed))
}
+ #[inline(always)]
fn seed_from_u64(seed: u64) -> Self {
Self::new(R::seed_from_u64(seed))
}
+ #[inline(always)]
fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
Ok(Self::new(R::from_rng(rng)?))
}
@@ -314,13 +278,10 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {
/// values. If the requested length is not a multiple of 8, some bytes will be
/// discarded.
///
-/// [`BlockRngCore`]: BlockRngCore.t.html
-/// [`RngCore`]: ../RngCore.t.html
-/// [`next_u32`]: ../trait.RngCore.html#tymethod.next_u32
-/// [`next_u64`]: ../trait.RngCore.html#tymethod.next_u64
-/// [`fill_bytes`]: ../trait.RngCore.html#tymethod.fill_bytes
-/// [`try_fill_bytes`]: ../trait.RngCore.html#tymethod.try_fill_bytes
-/// [`BlockRng`]: struct.BlockRng.html
+/// [`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<R: BlockRngCore + ?Sized> {
@@ -346,6 +307,7 @@ impl<R: BlockRngCore + fmt::Debug> fmt::Debug for BlockRng64<R> {
impl<R: BlockRngCore> BlockRng64<R> {
/// Create a new `BlockRng` from an existing RNG implementing
/// `BlockRngCore`. Results will be generated on first use.
+ #[inline]
pub fn new(core: R) -> BlockRng64<R>{
let results_empty = R::Results::default();
BlockRng64 {
@@ -361,12 +323,14 @@ impl<R: BlockRngCore> BlockRng64<R> {
/// 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.
+ #[inline(always)]
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.
+ #[inline]
pub fn reset(&mut self) {
self.index = self.results.as_ref().len();
self.half_used = false;
@@ -374,6 +338,7 @@ impl<R: BlockRngCore> BlockRng64<R> {
/// Generate a new set of results immediately, setting the index to the
/// given value.
+ #[inline]
pub fn generate_and_set(&mut self, index: usize) {
assert!(index < self.results.as_ref().len());
self.core.generate(&mut self.results);
@@ -385,7 +350,7 @@ impl<R: BlockRngCore> BlockRng64<R> {
impl<R: BlockRngCore<Item=u64>> RngCore for BlockRng64<R>
where <R as BlockRngCore>::Results: AsRef<[u64]> + AsMut<[u64]>
{
- #[inline(always)]
+ #[inline]
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 {
@@ -411,7 +376,7 @@ where <R as BlockRngCore>::Results: AsRef<[u64]> + AsMut<[u64]>
}
}
- #[inline(always)]
+ #[inline]
fn next_u64(&mut self) -> u64 {
if self.index >= self.results.as_ref().len() {
self.core.generate(&mut self.results);
@@ -424,48 +389,7 @@ where <R as BlockRngCore>::Results: AsRef<[u64]> + AsMut<[u64]>
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")))]
+ #[inline]
fn fill_bytes(&mut self, dest: &mut [u8]) {
let mut read_len = 0;
self.half_used = false;
@@ -484,22 +408,27 @@ where <R as BlockRngCore>::Results: AsRef<[u64]> + AsMut<[u64]>
}
}
+ #[inline(always)]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
- Ok(self.fill_bytes(dest))
+ self.fill_bytes(dest);
+ Ok(())
}
}
impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng64<R> {
type Seed = R::Seed;
+ #[inline(always)]
fn from_seed(seed: Self::Seed) -> Self {
Self::new(R::from_seed(seed))
}
+ #[inline(always)]
fn seed_from_u64(seed: u64) -> Self {
Self::new(R::seed_from_u64(seed))
}
+ #[inline(always)]
fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
Ok(Self::new(R::from_rng(rng)?))
}
diff --git a/rand/rand_core/src/error.rs b/rand/rand_core/src/error.rs
index 5a8459e..30b095c 100644
--- a/rand/rand_core/src/error.rs
+++ b/rand/rand_core/src/error.rs
@@ -9,169 +9,182 @@
//! Error types
use core::fmt;
+use core::num::NonZeroU32;
-#[cfg(feature="std")]
-use std::error::Error as stdError;
-#[cfg(feature="std")]
-use std::io;
-/// Error kind which can be matched over.
-#[derive(PartialEq, Eq, Debug, Copy, Clone)]
-pub enum ErrorKind {
- /// Feature is not available; not recoverable.
- ///
- /// This is the most permanent failure type and implies the error cannot be
- /// resolved simply by retrying (e.g. the feature may not exist in this
- /// build of the application or on the current platform).
- Unavailable,
- /// General failure; there may be a chance of recovery on retry.
- ///
- /// This is the catch-all kind for errors from known and unknown sources
- /// which do not have a more specific kind / handling method.
- ///
- /// It is suggested to retry a couple of times or retry later when
- /// handling; some error sources may be able to resolve themselves,
- /// although this is not likely.
- Unexpected,
- /// A transient failure which likely can be resolved or worked around.
- ///
- /// This error kind exists for a few specific cases where it is known that
- /// the error likely can be resolved internally, but is reported anyway.
- Transient,
- /// Not ready yet: recommended to try again a little later.
- ///
- /// This error kind implies the generator needs more time or needs some
- /// other part of the application to do something else first before it is
- /// ready for use; for example this may be used by external generators
- /// which require time for initialization.
- NotReady,
- #[doc(hidden)]
- __Nonexhaustive,
+/// Error type of random number generators
+///
+/// In order to be compatible with `std` and `no_std`, this type has two
+/// possible implementations: with `std` a boxed `Error` trait object is stored,
+/// while with `no_std` we merely store an error code.
+pub struct Error {
+ #[cfg(feature="std")]
+ inner: Box<dyn std::error::Error + Send + Sync + 'static>,
+ #[cfg(not(feature="std"))]
+ code: NonZeroU32,
}
-impl ErrorKind {
- /// True if this kind of error may resolve itself on retry.
+impl Error {
+ /// Construct from any type supporting `std::error::Error`
+ ///
+ /// Available only when configured with `std`.
///
- /// See also `should_wait()`.
- pub fn should_retry(self) -> bool {
- self != ErrorKind::Unavailable
+ /// See also `From<NonZeroU32>`, which is available with and without `std`.
+ #[cfg(feature="std")]
+ #[inline]
+ pub fn new<E>(err: E) -> Self
+ where E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>
+ {
+ Error { inner: err.into() }
}
- /// True if we should retry but wait before retrying
+ /// Reference the inner error (`std` only)
///
- /// This implies `should_retry()` is true.
- pub fn should_wait(self) -> bool {
- self == ErrorKind::NotReady
+ /// When configured with `std`, this is a trivial operation and never
+ /// panics. Without `std`, this method is simply unavailable.
+ #[cfg(feature="std")]
+ #[inline]
+ pub fn inner(&self) -> &(dyn std::error::Error + Send + Sync + 'static) {
+ &*self.inner
}
- /// A description of this error kind
- pub fn description(self) -> &'static str {
- match self {
- ErrorKind::Unavailable => "permanently unavailable",
- ErrorKind::Unexpected => "unexpected failure",
- ErrorKind::Transient => "transient failure",
- ErrorKind::NotReady => "not ready yet",
- ErrorKind::__Nonexhaustive => unreachable!(),
- }
+ /// Unwrap the inner error (`std` only)
+ ///
+ /// When configured with `std`, this is a trivial operation and never
+ /// panics. Without `std`, this method is simply unavailable.
+ #[cfg(feature="std")]
+ #[inline]
+ pub fn take_inner(self) -> Box<dyn std::error::Error + Send + Sync + 'static> {
+ self.inner
}
-}
-
+
+ /// Codes below this point represent OS Errors (i.e. positive i32 values).
+ /// Codes at or above this point, but below [`Error::CUSTOM_START`] are
+ /// reserved for use by the `rand` and `getrandom` crates.
+ pub const INTERNAL_START: u32 = 1 << 31;
-/// Error type of random number generators
-///
-/// This is a relatively simple error type, designed for compatibility with and
-/// without the Rust `std` library. It embeds a "kind" code, a message (static
-/// string only), and an optional chained cause (`std` only). The `kind` and
-/// `msg` fields can be accessed directly; cause can be accessed via
-/// `std::error::Error::cause` or `Error::take_cause`. Construction can only be
-/// done via `Error::new` or `Error::with_cause`.
-#[derive(Debug)]
-pub struct Error {
- /// The error kind
- pub kind: ErrorKind,
- /// The error message
- pub msg: &'static str,
- #[cfg(feature="std")]
- cause: Option<Box<stdError + Send + Sync>>,
-}
+ /// Codes at or above this point can be used by users to define their own
+ /// custom errors.
+ pub const CUSTOM_START: u32 = (1 << 31) + (1 << 30);
-impl Error {
- /// Create a new instance, with specified kind and a message.
- pub fn new(kind: ErrorKind, msg: &'static str) -> Self {
+ /// Extract the raw OS error code (if this error came from the OS)
+ ///
+ /// This method is identical to `std::io::Error::raw_os_error()`, except
+ /// that it works in `no_std` contexts. If this method returns `None`, the
+ /// error value can still be formatted via the `Diplay` implementation.
+ #[inline]
+ pub fn raw_os_error(&self) -> Option<i32> {
#[cfg(feature="std")] {
- Error { kind, msg, cause: None }
+ if let Some(e) = self.inner.downcast_ref::<std::io::Error>() {
+ return e.raw_os_error();
+ }
}
- #[cfg(not(feature="std"))] {
- Error { kind, msg }
+ match self.code() {
+ Some(code) if u32::from(code) < Self::INTERNAL_START =>
+ Some(u32::from(code) as i32),
+ _ => None,
}
}
-
- /// Create a new instance, with specified kind, message, and a
- /// chained cause.
- ///
- /// Note: `stdError` is an alias for `std::error::Error`.
- ///
- /// If not targetting `std` (i.e. `no_std`), this function is replaced by
- /// another with the same prototype, except that there are no bounds on the
- /// type `E` (because both `Box` and `stdError` are unavailable), and the
- /// `cause` is ignored.
- #[cfg(feature="std")]
- pub fn with_cause<E>(kind: ErrorKind, msg: &'static str, cause: E) -> Self
- where E: Into<Box<stdError + Send + Sync>>
- {
- Error { kind, msg, cause: Some(cause.into()) }
- }
-
- /// Create a new instance, with specified kind, message, and a
- /// chained cause.
+
+ /// Retrieve the error code, if any.
///
- /// In `no_std` mode the *cause* is ignored.
- #[cfg(not(feature="std"))]
- pub fn with_cause<E>(kind: ErrorKind, msg: &'static str, _cause: E) -> Self {
- Error { kind, msg }
+ /// If this `Error` was constructed via `From<NonZeroU32>`, then this method
+ /// will return this `NonZeroU32` code (for `no_std` this is always the
+ /// case). Otherwise, this method will return `None`.
+ #[inline]
+ pub fn code(&self) -> Option<NonZeroU32> {
+ #[cfg(feature="std")] {
+ self.inner.downcast_ref::<ErrorCode>().map(|c| c.0)
+ }
+ #[cfg(not(feature="std"))] {
+ Some(self.code)
+ }
}
-
- /// Take the cause, if any. This allows the embedded cause to be extracted.
- /// This uses `Option::take`, leaving `self` with no cause.
- #[cfg(feature="std")]
- pub fn take_cause(&mut self) -> Option<Box<stdError + Send + Sync>> {
- self.cause.take()
+}
+
+impl fmt::Debug for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ #[cfg(feature="std")] {
+ write!(f, "Error {{ inner: {:?} }}", self.inner)
+ }
+ #[cfg(all(feature="getrandom", not(feature="std")))] {
+ getrandom::Error::from(self.code).fmt(f)
+ }
+ #[cfg(not(feature="getrandom"))] {
+ write!(f, "Error {{ code: {} }}", self.code)
+ }
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[cfg(feature="std")] {
- if let Some(ref cause) = self.cause {
- return write!(f, "{} ({}); cause: {}",
- self.msg, self.kind.description(), cause);
- }
+ write!(f, "{}", self.inner)
+ }
+ #[cfg(all(feature="getrandom", not(feature="std")))] {
+ getrandom::Error::from(self.code).fmt(f)
+ }
+ #[cfg(not(feature="getrandom"))] {
+ write!(f, "error code {}", self.code)
}
- write!(f, "{} ({})", self.msg, self.kind.description())
}
}
-#[cfg(feature="std")]
-impl stdError for Error {
- fn description(&self) -> &str {
- self.msg
+impl From<NonZeroU32> for Error {
+ #[inline]
+ fn from(code: NonZeroU32) -> Self {
+ #[cfg(feature="std")] {
+ Error { inner: Box::new(ErrorCode(code)) }
+ }
+ #[cfg(not(feature="std"))] {
+ Error { code }
+ }
+ }
+}
+
+#[cfg(feature="getrandom")]
+impl From<getrandom::Error> for Error {
+ #[inline]
+ fn from(error: getrandom::Error) -> Self {
+ #[cfg(feature="std")] {
+ Error { inner: Box::new(error) }
+ }
+ #[cfg(not(feature="std"))] {
+ Error { code: error.code() }
+ }
}
+}
- fn cause(&self) -> Option<&stdError> {
- self.cause.as_ref().map(|e| e.as_ref() as &stdError)
+#[cfg(feature="std")]
+impl std::error::Error for Error {
+ #[inline]
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ self.inner.source()
}
}
#[cfg(feature="std")]
-impl From<Error> for io::Error {
+impl From<Error> for std::io::Error {
+ #[inline]
fn from(error: Error) -> Self {
- use std::io::ErrorKind::*;
- match error.kind {
- ErrorKind::Unavailable => io::Error::new(NotFound, error),
- ErrorKind::Unexpected |
- ErrorKind::Transient => io::Error::new(Other, error),
- ErrorKind::NotReady => io::Error::new(WouldBlock, error),
- ErrorKind::__Nonexhaustive => unreachable!(),
+ if let Some(code) = error.raw_os_error() {
+ std::io::Error::from_raw_os_error(code)
+ } else {
+ std::io::Error::new(std::io::ErrorKind::Other, error)
}
}
}
+
+#[cfg(feature="std")]
+#[derive(Debug, Copy, Clone)]
+struct ErrorCode(NonZeroU32);
+
+#[cfg(feature="std")]
+impl fmt::Display for ErrorCode {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "error code {}", self.0)
+ }
+}
+
+#[cfg(feature="std")]
+impl std::error::Error for ErrorCode {}
diff --git a/rand/rand_core/src/impls.rs b/rand/rand_core/src/impls.rs
index 57bdd07..dee4ed1 100644
--- a/rand/rand_core/src/impls.rs
+++ b/rand/rand_core/src/impls.rs
@@ -17,12 +17,11 @@
//! to/from byte sequences, and since its purpose is reproducibility,
//! non-reproducible sources (e.g. `OsRng`) need not bother with it.
-use core::intrinsics::transmute;
use core::ptr::copy_nonoverlapping;
use core::slice;
use core::cmp::min;
use core::mem::size_of;
-use RngCore;
+use crate::RngCore;
/// Implement `next_u64` via `next_u32`, little-endian order.
@@ -44,21 +43,15 @@ pub fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
while left.len() >= 8 {
let (l, r) = {left}.split_at_mut(8);
left = r;
- let chunk: [u8; 8] = unsafe {
- transmute(rng.next_u64().to_le())
- };
+ let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
l.copy_from_slice(&chunk);
}
let n = left.len();
if n > 4 {
- let chunk: [u8; 8] = unsafe {
- transmute(rng.next_u64().to_le())
- };
+ let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
left.copy_from_slice(&chunk[..n]);
} else if n > 0 {
- let chunk: [u8; 4] = unsafe {
- transmute(rng.next_u32().to_le())
- };
+ let chunk: [u8; 4] = rng.next_u32().to_le_bytes();
left.copy_from_slice(&chunk[..n]);
}
}
diff --git a/rand/rand_core/src/lib.rs b/rand/rand_core/src/lib.rs
index a65db93..d8e0189 100644
--- a/rand/rand_core/src/lib.rs
+++ b/rand/rand_core/src/lib.rs
@@ -8,29 +8,24 @@
// except according to those terms.
//! Random number generation traits
-//!
+//!
//! This crate is mainly of interest to crates publishing implementations of
-//! [`RngCore`]. Other users are encouraged to use the [rand] crate instead
+//! [`RngCore`]. Other users are encouraged to use the [`rand`] crate instead
//! which re-exports the main traits and error types.
//!
//! [`RngCore`] is the core trait implemented by algorithmic pseudo-random number
//! generators and external random-number sources.
-//!
+//!
//! [`SeedableRng`] is an extension trait for construction from fixed seeds and
//! other random number generators.
-//!
+//!
//! [`Error`] is provided for error-handling. It is safe to use in `no_std`
//! environments.
-//!
+//!
//! The [`impls`] and [`le`] sub-modules include a few small functions to assist
//! implementation of [`RngCore`].
-//!
-//! [rand]: https://crates.io/crates/rand
-//! [`RngCore`]: trait.RngCore.html
-//! [`SeedableRng`]: trait.SeedableRng.html
-//! [`Error`]: struct.Error.html
-//! [`impls`]: impls/index.html
-//! [`le`]: le/index.html
+//!
+//! [`rand`]: https://docs.rs/rand
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
@@ -40,59 +35,58 @@
#![deny(missing_debug_implementations)]
#![doc(test(attr(allow(unused_variables), deny(warnings))))]
-#![cfg_attr(not(feature="std"), no_std)]
-#![cfg_attr(all(feature="alloc", not(feature="std")), feature(alloc))]
+#![allow(clippy::unreadable_literal)]
-#[cfg(feature="std")] extern crate core;
-#[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;
+#![cfg_attr(not(feature="std"), no_std)]
use core::default::Default;
use core::convert::AsMut;
use core::ptr::copy_nonoverlapping;
+#[cfg(all(feature="alloc", not(feature="std")))] extern crate alloc;
#[cfg(all(feature="alloc", not(feature="std")))] use alloc::boxed::Box;
-pub use error::{ErrorKind, Error};
+pub use error::Error;
+#[cfg(feature="getrandom")] pub use os::OsRng;
mod error;
pub mod block;
pub mod impls;
pub mod le;
+#[cfg(feature="getrandom")] mod os;
/// The core of a random number generator.
-///
+///
/// This trait encapsulates the low-level functionality common to all
/// generators, and is the "back end", to be implemented by generators.
-/// End users should normally use [`Rng`] from the [rand] crate, which is
-/// automatically implemented for every type implementing `RngCore`.
-///
+/// End users should normally use the `Rng` trait from the [`rand`] crate,
+/// which is automatically implemented for every type implementing `RngCore`.
+///
/// Three different methods for generating random data are provided since the
/// optimal implementation of each is dependent on the type of generator. There
/// is no required relationship between the output of each; e.g. many
/// implementations of [`fill_bytes`] consume a whole number of `u32` or `u64`
/// values and drop any remaining unused bytes.
-///
+///
/// The [`try_fill_bytes`] method is a variant of [`fill_bytes`] allowing error
/// handling; it is not deemed sufficiently useful to add equivalents for
/// [`next_u32`] or [`next_u64`] since the latter methods are almost always used
/// with algorithmic generators (PRNGs), which are normally infallible.
-///
+///
/// Algorithmic generators implementing [`SeedableRng`] should normally have
/// *portable, reproducible* output, i.e. fix Endianness when converting values
/// to avoid platform differences, and avoid making any changes which affect
/// output (except by communicating that the release has breaking changes).
-///
+///
/// Typically implementators will implement only one of the methods available
/// in this trait directly, then use the helper functions from the
-/// [`rand_core::impls`] module to implement the other methods.
-///
+/// [`impls`] module to implement the other methods.
+///
/// It is recommended that implementations also implement:
-///
+///
/// - `Debug` with a custom implementation which *does not* print any internal
/// state (at least, [`CryptoRng`]s should not risk leaking state through
/// `Debug`).
@@ -104,72 +98,69 @@ pub mod le;
/// implement [`SeedableRng`], to guide users towards proper seeding.
/// External / hardware RNGs can choose to implement `Default`.
/// - `Eq` and `PartialEq` could be implemented, but are probably not useful.
-///
+///
/// # Example
-///
+///
/// A simple example, obviously not generating very *random* output:
-///
+///
/// ```
/// #![allow(dead_code)]
/// use rand_core::{RngCore, Error, impls};
-///
+///
/// struct CountingRng(u64);
-///
+///
/// impl RngCore for CountingRng {
/// fn next_u32(&mut self) -> u32 {
/// self.next_u64() as u32
/// }
-///
+///
/// fn next_u64(&mut self) -> u64 {
/// self.0 += 1;
/// self.0
/// }
-///
+///
/// fn fill_bytes(&mut self, dest: &mut [u8]) {
/// impls::fill_bytes_via_next(self, dest)
/// }
-///
+///
/// fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
/// Ok(self.fill_bytes(dest))
/// }
/// }
/// ```
-///
-/// [rand]: https://crates.io/crates/rand
-/// [`Rng`]: ../rand/trait.Rng.html
-/// [`SeedableRng`]: trait.SeedableRng.html
-/// [`rand_core::impls`]: ../rand_core/impls/index.html
-/// [`try_fill_bytes`]: trait.RngCore.html#tymethod.try_fill_bytes
-/// [`fill_bytes`]: trait.RngCore.html#tymethod.fill_bytes
-/// [`next_u32`]: trait.RngCore.html#tymethod.next_u32
-/// [`next_u64`]: trait.RngCore.html#tymethod.next_u64
-/// [`CryptoRng`]: trait.CryptoRng.html
+///
+/// [`rand`]: https://docs.rs/rand
+/// [`try_fill_bytes`]: RngCore::try_fill_bytes
+/// [`fill_bytes`]: RngCore::fill_bytes
+/// [`next_u32`]: RngCore::next_u32
+/// [`next_u64`]: RngCore::next_u64
pub trait RngCore {
/// Return the next random `u32`.
///
/// RNGs must implement at least one method from this trait directly. In
/// the case this method is not implemented directly, it can be implemented
- /// using `self.next_u64() as u32` or
- /// [via `fill_bytes`](../rand_core/impls/fn.next_u32_via_fill.html).
+ /// using `self.next_u64() as u32` or via
+ /// [`fill_bytes`](impls::next_u32_via_fill).
fn next_u32(&mut self) -> u32;
/// Return the next random `u64`.
///
/// RNGs must implement at least one method from this trait directly. In
/// the case this method is not implemented directly, it can be implemented
- /// [via `next_u32`](../rand_core/impls/fn.next_u64_via_u32.html) or
- /// [via `fill_bytes`](../rand_core/impls/fn.next_u64_via_fill.html).
+ /// via [`next_u32`](impls::next_u64_via_u32) or via
+ /// [`fill_bytes`](impls::next_u64_via_fill).
fn next_u64(&mut self) -> u64;
/// Fill `dest` with random data.
///
/// RNGs must implement at least one method from this trait directly. In
/// the case this method is not implemented directly, it can be implemented
- /// [via `next_u*`](../rand_core/impls/fn.fill_bytes_via_next.html) or
- /// via `try_fill_bytes`; if this generator can fail the implementation
- /// must choose how best to handle errors here (e.g. panic with a
- /// descriptive message or log a warning and retry a few times).
- ///
+ /// via [`next_u*`](impls::fill_bytes_via_next) or
+ /// via [`try_fill_bytes`](RngCore::try_fill_bytes); if this generator can
+ /// fail the implementation must choose how best to handle errors here
+ /// (e.g. panic with a descriptive message or log a warning and retry a few
+ /// times).
+ ///
/// This method should guarantee that `dest` is entirely filled
/// with new data, and may panic if this is impossible
/// (e.g. reading past the end of a file that is being used as the
@@ -182,51 +173,46 @@ pub trait RngCore {
/// generating random data thus making this the primary method implemented
/// by external (true) RNGs (e.g. `OsRng`) which can fail. It may be used
/// directly to generate keys and to seed (infallible) PRNGs.
- ///
+ ///
/// Other than error handling, this method is identical to [`fill_bytes`];
/// thus this may be implemented using `Ok(self.fill_bytes(dest))` or
/// `fill_bytes` may be implemented with
/// `self.try_fill_bytes(dest).unwrap()` or more specific error handling.
- ///
- /// [`fill_bytes`]: trait.RngCore.html#method.fill_bytes
+ ///
+ /// [`fill_bytes`]: RngCore::fill_bytes
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.
-///
-/// [`RngCore`]: trait.RngCore.html
-/// [`BlockRngCore`]: ../rand_core/block/trait.BlockRngCore.html
+///
+/// [`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
/// pseudo-random number generators (PRNGs, or algorithmic generators).
-///
-/// The [`rand::FromEntropy`] trait is automatically implemented for every type
-/// implementing `SeedableRng`, providing a convenient `from_entropy()`
-/// constructor.
-///
-/// [`rand::FromEntropy`]: ../rand/trait.FromEntropy.html
+///
+/// [`rand`]: https://docs.rs/rand
pub trait SeedableRng: Sized {
/// Seed type, which is restricted to types mutably-dereferencable as `u8`
/// arrays (we recommend `[u8; N]` for some `N`).
@@ -279,14 +265,18 @@ pub trait SeedableRng: Sized {
///
/// PRNG implementations are allowed to assume that bits in the seed are
/// well distributed. That means usually that the number of one and zero
- /// bits are about equal, and values like 0, 1 and (size - 1) are unlikely.
+ /// bits are roughly equal, and values like 0, 1 and (size - 1) are unlikely.
+ /// Note that many non-cryptographic PRNGs will show poor quality output
+ /// if this is not adhered to. If you wish to seed from simple numbers, use
+ /// `seed_from_u64` instead.
///
- /// PRNG implementations are recommended to be reproducible. A PRNG seeded
- /// using this function with a fixed seed should produce the same sequence
- /// of output in the future and on different architectures (with for example
- /// different endianness).
+ /// All PRNG implementations should be reproducible unless otherwise noted:
+ /// given a fixed `seed`, the same sequence of output should be produced
+ /// on all runs, library versions and architectures (e.g. check endianness).
+ /// Any "value-breaking" changes to the generator should require bumping at
+ /// least the minor version and documentation of the change.
///
- /// It is however not required that this function yield the same state as a
+ /// It is not required that this function yield the same state as a
/// reference implementation of the PRNG given equivalent seed; if necessary
/// another constructor replicating behaviour from a reference
/// implementation can be added.
@@ -297,17 +287,17 @@ pub trait SeedableRng: Sized {
/// for example `0xBAD5EEDu32` or `0x0DDB1A5E5BAD5EEDu64` ("odd biases? bad
/// seed"). This is assuming only a small number of values must be rejected.
fn from_seed(seed: Self::Seed) -> Self;
-
+
/// Create a new PRNG using a `u64` seed.
- ///
+ ///
/// This is a convenience-wrapper around `from_seed` to allow construction
/// of any `SeedableRng` from a simple `u64` value. It is designed such that
/// low Hamming Weight numbers like 0 and 1 can be used and should still
/// result in good, independent seeds to the PRNG which is returned.
- ///
+ ///
/// This **is not suitable for cryptography**, as should be clear given that
/// the input size is only 64 bits.
- ///
+ ///
/// Implementations for PRNGs *may* provide their own implementations of
/// this function, but the default implementation should be good enough for
/// all purposes. *Changing* the implementation of this function should be
@@ -316,64 +306,80 @@ pub trait SeedableRng: Sized {
// We use PCG32 to generate a u32 sequence, and copy to the seed
const MUL: u64 = 6364136223846793005;
const INC: u64 = 11634580027462260723;
-
+
let mut seed = Self::Seed::default();
for chunk in seed.as_mut().chunks_mut(4) {
// We advance the state first (to get away from the input value,
// in case it has low Hamming Weight).
state = state.wrapping_mul(MUL).wrapping_add(INC);
-
+
// Use PCG output function with to_le to generate x:
let xorshifted = (((state >> 18) ^ state) >> 27) as u32;
let rot = (state >> 59) as u32;
let x = xorshifted.rotate_right(rot).to_le();
-
+
unsafe {
let p = &x as *const u32 as *const u8;
copy_nonoverlapping(p, chunk.as_mut_ptr(), chunk.len());
}
}
-
+
Self::from_seed(seed)
}
-
+
/// Create a new PRNG seeded from another `Rng`.
///
- /// This is the recommended way to initialize PRNGs with fresh entropy. The
- /// [`FromEntropy`] trait provides a convenient `from_entropy` method
- /// based on `from_rng`.
- ///
- /// Usage of this method is not recommended when reproducibility is required
- /// since implementing PRNGs are not required to fix Endianness and are
- /// allowed to modify implementations in new releases.
- ///
- /// It is important to use a good source of randomness to initialize the
- /// PRNG. Cryptographic PRNG may be rendered insecure when seeded from a
- /// non-cryptographic PRNG or with insufficient entropy.
- /// Many non-cryptographic PRNGs will show statistical bias in their first
- /// results if their seed numbers are small or if there is a simple pattern
- /// between them.
- ///
- /// Prefer to seed from a strong external entropy source like [`OsRng`] or
- /// from a cryptographic PRNG; if creating a new generator for cryptographic
- /// uses you *must* seed from a strong source.
- ///
- /// Seeding a small PRNG from another small PRNG is possible, but
- /// something to be careful with. An extreme example of how this can go
- /// wrong is seeding an Xorshift RNG from another Xorshift RNG, which
- /// will effectively clone the generator. In general seeding from a
- /// generator which is hard to predict is probably okay.
+ /// This may be useful when needing to rapidly seed many PRNGs from a master
+ /// PRNG, and to allow forking of PRNGs. It may be considered deterministic.
+ ///
+ /// The master PRNG should be at least as high quality as the child PRNGs.
+ /// When seeding non-cryptographic child PRNGs, we recommend using a
+ /// different algorithm for the master PRNG (ideally a CSPRNG) to avoid
+ /// correlations between the child PRNGs. If this is not possible (e.g.
+ /// forking using small non-crypto PRNGs) ensure that your PRNG has a good
+ /// mixing function on the output or consider use of a hash function with
+ /// `from_seed`.
+ ///
+ /// Note that seeding `XorShiftRng` from another `XorShiftRng` provides an
+ /// extreme example of what can go wrong: the new PRNG will be a clone
+ /// of the parent.
///
/// PRNG implementations are allowed to assume that a good RNG is provided
/// for seeding, and that it is cryptographically secure when appropriate.
- ///
- /// [`FromEntropy`]: ../rand/trait.FromEntropy.html
- /// [`OsRng`]: ../rand/rngs/struct.OsRng.html
+ /// As of `rand` 0.7 / `rand_core` 0.5, implementations overriding this
+ /// method should ensure the implementation satisfies reproducibility
+ /// (in prior versions this was not required).
+ ///
+ /// [`rand`]: https://docs.rs/rand
+ /// [`rand_os`]: https://docs.rs/rand_os
fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
let mut seed = Self::Seed::default();
rng.try_fill_bytes(seed.as_mut())?;
Ok(Self::from_seed(seed))
}
+
+ /// Creates a new instance of the RNG seeded via [`getrandom`].
+ ///
+ /// This method is the recommended way to construct non-deterministic PRNGs
+ /// since it is convenient and secure.
+ ///
+ /// In case the overhead of using [`getrandom`] to seed *many* PRNGs is an
+ /// issue, one may prefer to seed from a local PRNG, e.g.
+ /// `from_rng(thread_rng()).unwrap()`.
+ ///
+ /// # Panics
+ ///
+ /// If [`getrandom`] is unable to provide secure entropy this method will panic.
+ ///
+ /// [`getrandom`]: https://docs.rs/getrandom
+ #[cfg(feature="getrandom")]
+ fn from_entropy() -> Self {
+ let mut seed = Self::Seed::default();
+ if let Err(err) = getrandom::getrandom(seed.as_mut()) {
+ panic!("from_entropy failed: {}", err);
+ }
+ Self::from_seed(seed)
+ }
}
// Implement `RngCore` for references to an `RngCore`.
@@ -428,7 +434,7 @@ impl<R: RngCore + ?Sized> RngCore for Box<R> {
}
#[cfg(feature="std")]
-impl std::io::Read for RngCore {
+impl std::io::Read for dyn RngCore {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
self.try_fill_bytes(buf)?;
Ok(buf.len())
@@ -445,7 +451,7 @@ impl<R: CryptoRng + ?Sized> CryptoRng for Box<R> {}
#[cfg(test)]
mod test {
use super::*;
-
+
#[test]
fn test_seed_from_u64() {
struct SeedableNum(u64);
@@ -457,7 +463,7 @@ mod test {
SeedableNum(x[0])
}
}
-
+
const N: usize = 8;
const SEEDS: [u64; N] = [0u64, 1, 2, 3, 4, 8, 16, -1i64 as u64];
let mut results = [0u64; N];
@@ -465,21 +471,21 @@ mod test {
let SeedableNum(x) = SeedableNum::seed_from_u64(*seed);
results[i] = x;
}
-
+
for (i1, r1) in results.iter().enumerate() {
let weight = r1.count_ones();
// This is the binomial distribution B(64, 0.5), so chance of
// weight < 20 is binocdf(19, 64, 0.5) = 7.8e-4, and same for
// weight > 44.
assert!(weight >= 20 && weight <= 44);
-
+
for (i2, r2) in results.iter().enumerate() {
if i1 == i2 { continue; }
let diff_weight = (r1 ^ r2).count_ones();
assert!(diff_weight >= 20);
}
}
-
+
// value-breakage test:
assert_eq!(results[0], 5029875928683246316);
}
diff --git a/rand/rand_core/src/os.rs b/rand/rand_core/src/os.rs
new file mode 100644
index 0000000..fc23a57
--- /dev/null
+++ b/rand/rand_core/src/os.rs
@@ -0,0 +1,85 @@
+// Copyright 2019 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Interface to the random number generator of the operating system.
+// Note: keep this code in sync with the rand_os crate!
+
+use getrandom::getrandom;
+use crate::{CryptoRng, RngCore, Error, impls};
+
+/// A random number generator that retrieves randomness from from the
+/// operating system.
+///
+/// This is a zero-sized struct. It can be freely constructed with `OsRng`.
+///
+/// The implementation is provided by the [getrandom] crate. Refer to
+/// [getrandom] documentation for details.
+///
+/// This struct is only available when specifying the crate feature `getrandom`
+/// or `std`. When using the `rand` lib, it is also available as `rand::rngs::OsRng`.
+///
+/// # Blocking and error handling
+///
+/// It is possible that when used during early boot the first call to `OsRng`
+/// will block until the system's RNG is initialised. It is also possible
+/// (though highly unlikely) for `OsRng` to fail on some platforms, most
+/// likely due to system mis-configuration.
+///
+/// After the first successful call, it is highly unlikely that failures or
+/// significant delays will occur (although performance should be expected to
+/// be much slower than a user-space PRNG).
+///
+/// # Usage example
+/// ```
+/// use rand_core::{RngCore, OsRng};
+///
+/// let mut key = [0u8; 16];
+/// OsRng.fill_bytes(&mut key);
+/// let random_u64 = OsRng.next_u64();
+/// ```
+///
+/// [getrandom]: https://crates.io/crates/getrandom
+#[derive(Clone, Copy, Debug, Default)]
+pub struct OsRng;
+
+impl CryptoRng for OsRng {}
+
+impl RngCore for OsRng {
+ fn next_u32(&mut self) -> u32 {
+ impls::next_u32_via_fill(self)
+ }
+
+ fn next_u64(&mut self) -> u64 {
+ impls::next_u64_via_fill(self)
+ }
+
+ fn fill_bytes(&mut self, dest: &mut [u8]) {
+ if let Err(e) = self.try_fill_bytes(dest) {
+ panic!("Error: {}", e);
+ }
+ }
+
+ fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
+ getrandom(dest)?;
+ Ok(())
+ }
+}
+
+#[test]
+fn test_os_rng() {
+ let x = OsRng.next_u64();
+ let y = OsRng.next_u64();
+ assert!(x != 0);
+ assert!(x != y);
+}
+
+#[test]
+fn test_construction() {
+ let mut rng = OsRng::default();
+ assert!(rng.next_u64() != 0);
+}