// Hide badges from generated docs
//! <style> .badges { display: none; } </style>

#![no_std]
#![doc = include_str!("../README.md")]
#![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"
)]

use core::ops::DerefMut;

pub use core::convert::Infallible;

pub mod block;
pub mod utils;

mod seedable_rng;
mod unwrap_err;
mod word;

pub use seedable_rng::SeedableRng;
pub use unwrap_err::UnwrapErr;

/// Trait for infallible random number generators
///
/// `Rng` is a sub-trait of [`TryRng`] for infallible generators.
///
/// # Requirements
///
/// See [`TryRng`#Requirements] which also apply here.
///
/// # Usage
///
/// The [`rand`] crate provides higher level functionality, for example
/// generation of floating-point values, uniform ranged sampling and shuffling
/// sequences. In particular, [`rand::RngExt`] is an extension trait over `Rng`
/// providing many of the methods one might expect to be able to use on an RNG.
///
/// # Implementing `Rng`
///
/// Implement [`TryRng`] with <code>type Error = [core::convert::Infallible][]</code>.
///
/// [`rand`]: https://docs.rs/rand/
/// [`rand::RngExt`]: https://docs.rs/rand/latest/rand/trait.RngExt.html
/// [`fill_bytes`]: Rng::fill_bytes
/// [`next_u32`]: Rng::next_u32
/// [`next_u64`]: Rng::next_u64
pub trait Rng: TryRng<Error = Infallible> {
    /// Return the next random `u32`.
    fn next_u32(&mut self) -> u32;

    /// Return the next random `u64`.
    fn next_u64(&mut self) -> u64;

    /// Fill `dest` with random data.
    ///
    /// 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
    /// source of randomness).
    fn fill_bytes(&mut self, dst: &mut [u8]);
}

impl<R> Rng for R
where
    R: TryRng<Error = Infallible> + ?Sized,
{
    #[inline]
    fn next_u32(&mut self) -> u32 {
        match self.try_next_u32() {
            Ok(x) => x,
        }
    }

    #[inline]
    fn next_u64(&mut self) -> u64 {
        match self.try_next_u64() {
            Ok(x) => x,
        }
    }

    #[inline]
    fn fill_bytes(&mut self, dst: &mut [u8]) {
        match self.try_fill_bytes(dst) {
            Ok(()) => (),
        }
    }
}

/// A marker trait for securely unpredictable infallible RNGs
///
/// This is a convenient trait alias for <code>[TryCryptoRng]<Error = [Infallible]></code>.
/// It is equivalent to the trait sum <code>[Rng] + [TryCryptoRng]</code>.
pub trait CryptoRng: Rng + TryCryptoRng<Error = Infallible> {}

impl<R> CryptoRng for R where R: TryCryptoRng<Error = Infallible> + ?Sized {}

/// Base trait for random number generators and random data sources
///
/// This trait provides a base interface designed to support efficient usage of
/// (`u32`, `u64`) word generators, block generators and random data sources.
/// There is no required relationship between the output of each method or any
/// requirement to use all generated random bits; for example an implementation
/// of [`try_fill_bytes`](Self::try_fill_bytes) may discard some generated bytes
/// to avoid storing a partially used word or block.
///
/// # Requirements
///
/// ### Quality and length
///
/// Implementions should produce bits uniformly: each output value should be
/// equally likely, without observable patterns in successive outputs or
/// between the output streams of multiple instances of an implementation using
/// different seeds or streams (where supported by the implementation).
///
/// Pathological implementations (e.g. constant or counting generators which
/// rarely change some bits) may cause issues in consumers of random data, for
/// example dead-locks in rejection samplers and obviously non-random output
/// (e.g. a counting generator may result in apparently-constant output from a
/// uniform-ranged distribution).
///
/// Cryptographically unpredictable output is not a requirement of this trait,
/// but is a requirement of [`TryCryptoRng`].
///
/// In practice, most implementations are pseudo-random number generators with a
/// finite *period* or *cycle length*, and (among non-cryptographic PRNGs)
/// statistical anomalies may appear long before a cycle occurs. An
/// implementation should ensure its period is sufficiently long that no
/// anomalies are likely to appear in usage and/or document its limitations.
///
/// For more on PRNG quality and period, see [The Rust Rand Book: Quality][0].
///
/// [0]: https://rust-random.github.io/book/guide-rngs.html#quality
///
/// ### Reproducibility
///
/// 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).
/// See also [The Rust Rand Book: Reproducibility][1].
///
/// [1]: https://rust-random.github.io/book/crate-reprod.html
///
/// # Usage
///
/// Often, usage of the infallible trait [`Rng`] or its extension trait
/// [`rand::RngExt`] is preferred to direct usage of `TryRng`.
//
/// Many implementations of `TryRng` (those with <code>type Error = [Infallible][]</code>)
/// already implement [`Rng`]; in other cases [`UnwrapErr`] may be used to obtain
/// an implementation of [`Rng`].
///
/// # Implementing `TryRng`
///
/// Most algorithmic generators (i.e. pseudo-random number generators or PRNGs)
/// never fail; in this case type `Error` should be [`Infallible`]; in this case
/// trait `Rng` is implemented automatically. Cycling is not considered an
/// error.
///
/// Small PRNGs often yield either `u32` or `u64` natively.
/// Module [`crate::utils`] provides utilities to help implement other methods.
///
/// Byte sources may implement [`try_fill_bytes`](Self::try_fill_bytes)
/// natively.
/// Module [`crate::utils`] provides utilities to help implement other methods.
///
/// Block generators (which produce `[u32; N]` or `[u64; N]` for some fixed `N`)
/// should make use of the [`crate::block`] module.
///
/// With regards to other traits:
///
/// - **Do not** implement [`Default`] for seedable pseudorandom generators,
///   though the trait may be implemented for stateless interfaces and
///   auto-seeding generators.
/// - **Do** implement [`SeedableRng`] for seedable pseudorandom generators. See
///   [Reproducibility](#reproducibility) above.
/// - Implement [`Clone`] for non-cryptographic PRNGs but consider not doing so
///   for cryptographic generators to avoid the risk of key-stream duplication.
/// - **Do not** implement [`Copy`] since accidental copies may cause repeated
///   values.
/// - Implement [`Debug`](core::fmt::Debug), except that cryptographic PRNGs
///   should use a custom implementation which avoids leaking internal state (or
///   the subset of this derived from the key).
/// - [`Eq`] and [`PartialEq`] could be implemented, but are probably not useful.
///
/// [`rand::RngExt`]: https://docs.rs/rand/latest/rand/trait.RngExt.html
pub trait TryRng {
    /// The type returned in the event of a RNG error.
    ///
    /// Use type [`Infallible`] (re-exported by `rand_core`) for infallible implementations.
    type Error: core::error::Error;

    /// Return the next random `u32`.
    fn try_next_u32(&mut self) -> Result<u32, Self::Error>;
    /// Return the next random `u64`.
    fn try_next_u64(&mut self) -> Result<u64, Self::Error>;
    /// Fill `dst` entirely with random data.
    fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error>;
}

impl<R: DerefMut> TryRng for R
where
    R::Target: TryRng,
{
    type Error = <R::Target as TryRng>::Error;

    #[inline]
    fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
        self.deref_mut().try_next_u32()
    }

    #[inline]
    fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
        self.deref_mut().try_next_u64()
    }

    #[inline]
    fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
        self.deref_mut().try_fill_bytes(dst)
    }
}

/// A marker trait over [`TryRng`] for securely unpredictable RNGs
///
/// This marker trait indicates that the implementing generator is intended,
/// when correctly seeded and protected from side-channel attacks such as a
/// leaking of state, to be a cryptographically secure generator. This trait is
/// provided as a tool to aid review of cryptographic code, but does not by
/// itself guarantee suitability for cryptographic applications.
///
/// Formally, a CSPRNG (Cryptographically Secure Pseudo-Random Number Generator)
/// should satisfy an additional property over other generators: assuming that
/// the generator has been appropriately seeded and has unknown state, then
/// 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%.
///
/// An optional property of CSPRNGs is backtracking resistance: if the CSPRNG's
/// state is revealed, it will not be computationally-feasible to reconstruct
/// prior output values. This property is not required by `CryptoRng`.
///
/// Implementors of `TryCryptoRng` should only implement [`Default`] if a
/// default-constructed instance is itself a secure generator, for example
/// [`getrandom::SysRng`] which is a stateless interface.
///
/// [`getrandom::SysRng`]: https://docs.rs/getrandom/latest/getrandom/struct.SysRng.html
pub trait TryCryptoRng: TryRng {}

impl<R: DerefMut> TryCryptoRng for R where R::Target: TryCryptoRng {}

/// DEPRECATED: stub trait to print a deprecation warning and aid discovering that [`Rng`] is the
/// replacement.
// TODO: remove prior to v1.x.
#[deprecated(since = "0.10.0", note = "use `Rng` instead")]
pub trait RngCore: Rng {}
#[allow(deprecated)]
impl<R: Rng> RngCore for R {}

/// DEPRECATED: stub trait to print a deprecation warning and aid discovering that [`TryRng`] is the
/// replacement.
// TODO: remove prior to v1.x.
#[deprecated(since = "0.10.0", note = "use `TryRng` instead")]
pub trait TryRngCore: TryRng {
    /// Error type.
    type Error: core::error::Error;
}
#[allow(deprecated)]
impl<R: TryRng> TryRngCore for R {
    type Error = R::Error;
}
