Skip to main content

vitaminc_random/
lib.rs

1#![doc = include_str!("../README.md")]
2use thiserror::Error;
3mod bounded;
4mod generatable;
5mod safe_rand;
6
7pub use bounded::BoundedRng;
8#[allow(deprecated)]
9pub use bounded::BoundedRngInclusive;
10#[doc(inline)]
11pub use generatable::Generatable;
12pub use safe_rand::SafeRand;
13
14// Re-exports
15pub use rand::{Fill, Rng, SeedableRng};
16
17/// Derive macro for `Generatable`
18pub use vitaminc_random_derives::Generatable;
19
20#[derive(Error, Debug)]
21pub enum RandomError {
22    #[error("Generation failed")]
23    GenerationFailed,
24    #[error("Seeding from OS RNG failed: {0}")]
25    SeedingFailed(#[from] rand::rngs::SysError),
26    /// The seed produced an unusable batch of randomness (e.g. colliding
27    /// sort keys during oblivious permutation generation). The seed must be
28    /// discarded and a fresh one generated; retrying from the same seed's
29    /// RNG stream would leak a predicate of the retained seed through timing
30    /// and can never yield a stable derivation for it.
31    ///
32    /// For a generator seeded from the OS rather than from a retained seed
33    /// ([`SafeRand::from_entropy`]) there is no seed to keep: build a new
34    /// generator with `from_entropy` and call again. What must not happen
35    /// is a second draw from the *same* generator.
36    #[error("The seed produced an unusable batch; discard it and generate a fresh seed")]
37    SeedRejected,
38}
39
40#[cfg(test)]
41mod tests {
42    use super::{Generatable, SafeRand};
43    use std::num::NonZeroU16;
44
45    #[test]
46    fn test_generate_nonzerou16() -> Result<(), crate::RandomError> {
47        let mut rng = SafeRand::from_entropy()?;
48        let value: NonZeroU16 = Generatable::random(&mut rng)?;
49        assert_ne!(value.get(), 0);
50        Ok(())
51    }
52}