1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! This is a library that implements the [WyRand](rand_wyrand::WyRand) PRNG for
//! the [RngCore](rand_core::RngCore) trait from `rand`. It is completely
//! `#![no_std]`, and does not require the Rust standard library.
//!
//! WyRand is an extremely fast, stable, and solid PRNG. While not
//! cryptographically secure, it still passes the BigCrush and practrand tests,
//! making it a solid choice for non-secure applications. (Basically, just don't
//! use it to like, generate cryptographic keys or passwords or whatever)
//!
//! ## Examples
//!
//! ### Generate random number from 1 to 100
//!
//! ```rust
//! use rand::{Rng, SeedableRng};
//! use rand_wyrand::WyRand;
//!
//! let mut wyrand = WyRand::from_entropy();
//! let mut bytes = [0_u8; 64];
//! wyrand.fill(&mut bytes);
//! println!("Random bytes: {bytes:?}");
//! ```
//!
//! ### Generate random bytes
//!
//! ```rust
//! use rand::{Rng, SeedableRng};
//! use rand_wyrand::WyRand;
//!
//! let mut wyrand = WyRand::from_entropy();
//! println!("Random number from 1 to 100: {}", wyrand.gen_range(1..=100));
//! ```
//!
//! ### Generate random string
//!
//! ```rust
//! use rand::{distributions::Alphanumeric, Rng, SeedableRng};
//! use rand_wyrand::WyRand;
//!
//! let mut wyrand = WyRand::from_entropy();
//! let rand_string: String = wyrand
//! .sample_iter(&Alphanumeric)
//! .take(16)
//! .map(char::from)
//! .collect();
//! println!("Random string: {rand_string}")
//! ```
//!
//! ## License
//!
//! `rand-wyrand` is licensed under either the [Apache
//! License](LICENSE-APACHE.md) or the [MIT License](LICENSE-MIT.md), at your
//! choice.
#![no_std]
#![forbid(unsafe_code)]
#![deny(clippy::perf, clippy::style, clippy::correctness, clippy::complexity)]
#![allow(clippy::tabs_in_doc_comments)]
use rand_core::{impls::fill_bytes_via_next, Error, RngCore, SeedableRng};
/// An instance of the [WyRand](https://github.com/wangyi-fudan/wyhash) random number generator.
///
/// While not cryptographically secure, WyRand is solid enough to pass
/// the [BigCrush](https://en.wikipedia.org/wiki/TestU01) and
/// [practrand](http://pracrand.sourceforge.net/) tests, while being extremely fast, making it ideal
/// for non-secure uses.
///
/// ## Examples
///
/// ### Generate random number from 1 to 100
///
/// ```rust
/// use rand::{Rng, SeedableRng};
/// use rand_wyrand::WyRand;
///
/// let mut wyrand = WyRand::from_entropy();
/// let mut bytes = [0_u8; 64];
/// wyrand.fill(&mut bytes);
/// println!("Random bytes: {bytes:?}");
/// ```
///
/// ### Generate random bytes
///
/// ```rust
/// use rand::{Rng, SeedableRng};
/// use rand_wyrand::WyRand;
///
/// let mut wyrand = WyRand::from_entropy();
/// println!("Random number from 1 to 100: {}", wyrand.gen_range(1..=100));
/// ```
///
/// ### Generate random string
///
/// ```rust
/// use rand::{distributions::Alphanumeric, Rng, SeedableRng};
/// use rand_wyrand::WyRand;
///
/// let mut wyrand = WyRand::from_entropy();
/// let rand_string: String = wyrand
/// .sample_iter(&Alphanumeric)
/// .take(16)
/// .map(char::from)
/// .collect();
/// println!("Random string: {rand_string}")
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct WyRand {
seed: u64,
}
impl RngCore for WyRand {
#[inline]
fn next_u32(&mut self) -> u32 {
self.next_u64() as u32
}
#[inline]
fn next_u64(&mut self) -> u64 {
self.seed = self.seed.wrapping_add(0xa0761d6478bd642f);
let t: u128 = (self.seed as u128).wrapping_mul((self.seed ^ 0xe7037ed1a0b428db) as u128);
(t.wrapping_shr(64) ^ t) as u64
}
#[inline]
fn fill_bytes(&mut self, dest: &mut [u8]) {
fill_bytes_via_next(self, dest)
}
#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
self.fill_bytes(dest);
Ok(())
}
}
impl SeedableRng for WyRand {
type Seed = [u8; core::mem::size_of::<u64>()];
#[inline]
fn from_seed(seed: Self::Seed) -> Self {
Self::seed_from_u64(u64::from_le_bytes(seed))
}
#[inline]
fn seed_from_u64(state: u64) -> Self {
Self { seed: state }
}
#[inline]
fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
Ok(Self::seed_from_u64(rng.next_u64()))
}
}