mod_rand/lib.rs
1//! # mod-rand
2//!
3//! Tiered random number generation for Rust. Zero dependencies. Pick
4//! the tier appropriate to your threat model.
5//!
6//! ## Tiers
7//!
8//! - **[`tier1`]**: Deterministic seedable PRNG (xoshiro256\*\*).
9//! For simulation, fixture data, non-security shuffling. Always
10//! available, works in `no_std`.
11//! - **[`tier2`]**: Process-unique seeds derived from PID + time +
12//! counter. For tempdir names, request IDs, log correlation. Fast
13//! enough for high-frequency use. Not cryptographic.
14//! - **[`tier3`]**: OS-backed cryptographic random. For tokens, keys,
15//! session IDs. Calls platform syscalls directly.
16//!
17//! ## Quick example
18//!
19//! Raw draws:
20//!
21//! ```
22//! use mod_rand::tier1::Xoshiro256;
23//!
24//! let mut rng = Xoshiro256::seed_from_u64(42);
25//! let n: u64 = rng.next_u64();
26//! # let _ = n;
27//! ```
28//!
29//! Bounded ranges — every tier exposes a parallel `gen_range_*` /
30//! `range_*` / `random_range_*` family that uses Lemire's "Nearly
31//! Divisionless" rejection sampling under the hood, so output is
32//! uniformly distributed with no modulo bias:
33//!
34//! ```
35//! use mod_rand::tier1::Xoshiro256;
36//!
37//! let mut rng = Xoshiro256::seed_from_u64(42);
38//!
39//! // Half-open: never returns 100.
40//! let pct: u32 = rng.gen_range_u32(0..100);
41//!
42//! // Inclusive: classic six-sided die.
43//! let d6: u32 = rng.gen_range_inclusive_u32(1..=6);
44//! # let _ = (pct, d6);
45//! ```
46//!
47//! The same `..` (half-open) vs `..=` (inclusive) convention applies
48//! on Tier 2 (free functions) and Tier 3 (free functions returning
49//! `io::Result`):
50//!
51//! ```no_run
52//! # #[cfg(all(feature = "tier2", feature = "tier3"))]
53//! # fn demo() -> std::io::Result<()> {
54//! use mod_rand::{tier2, tier3};
55//!
56//! let id = tier2::range_inclusive_u32(1..=1_000);
57//! let key = tier3::random_range_inclusive_u64(0..=u64::MAX)?;
58//! # let _ = (id, key);
59//! # Ok(())
60//! # }
61//! ```
62//!
63//! ## Choosing a tier
64//!
65//! | Use case | Tier |
66//! |-----------------------------------|------|
67//! | Test fixtures, simulation | 1 |
68//! | Tempdir names, request IDs | 2 |
69//! | Auth tokens, session IDs, keys | 3 |
70//!
71//! ## Status
72//!
73//! The `0.9.x` line ships the real algorithms: full xoshiro256\*\*
74//! with splitmix64 seeding (Tier 1), Stafford-mix-13 over (PID +
75//! nanos + atomic counter + per-process salt) (Tier 2), and direct
76//! platform syscalls for Tier 3 (`getrandom(2)` / `BCryptGenRandom` /
77//! `getentropy(3)`). All bounded-range methods use Lemire's
78//! "Nearly Divisionless" rejection sampling, verified for uniformity
79//! by 1,000,000-draw chi-squared tests at the integration level.
80//! The API is stable through the `0.9.x` series; `1.0` will pin it.
81//! See the [CHANGELOG](https://github.com/jamesgober/mod-rand/blob/main/CHANGELOG.md)
82//! for release history.
83
84#![cfg_attr(docsrs, feature(doc_cfg))]
85#![cfg_attr(not(feature = "std"), no_std)]
86#![warn(missing_docs)]
87#![warn(rust_2018_idioms)]
88
89pub mod tier1;
90
91#[cfg(feature = "tier2")]
92pub mod tier2;
93
94#[cfg(feature = "tier3")]
95pub mod tier3;