// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// 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.

//! Entropy generator, or wrapper around external generators

use rand_core::{RngCore, CryptoRng, Error, impls};
use {OsRng, JitterRng};

/// An RNG provided specifically for seeding PRNGs.
/// 
/// Where possible, `EntropyRng` retrieves random data from the operating
/// system's interface for random numbers ([`OsRng`]); if that fails it will
/// fall back to the [`JitterRng`] entropy collector. In the latter case it will
/// still try to use [`OsRng`] on the next usage.
/// 
/// This is either a little slow ([`OsRng`] requires a system call) or extremely
/// slow ([`JitterRng`] must use significant CPU time to generate sufficient
/// jitter). It is recommended to only use `EntropyRng` to seed a PRNG (as in
/// [`thread_rng`]) or to generate a small key.
///
/// [`OsRng`]: os/struct.OsRng.html
/// [`JitterRng`]: jitter/struct.JitterRng.html
/// [`thread_rng`]: fn.thread_rng.html
#[derive(Debug)]
pub struct EntropyRng {
    rng: EntropySource,
}

#[derive(Debug)]
enum EntropySource {
    Os(OsRng),
    Jitter(JitterRng),
    None,
}

impl EntropyRng {
    /// Create a new `EntropyRng`.
    ///
    /// This method will do no system calls or other initialization routines,
    /// those are done on first use. This is done to make `new` infallible,
    /// and `try_fill_bytes` the only place to report errors.
    pub fn new() -> Self {
        EntropyRng { rng: EntropySource::None }
    }
}

impl RngCore for EntropyRng {
    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]) {
        self.try_fill_bytes(dest).unwrap_or_else(|err|
                panic!("all entropy sources failed; first error: {}", err))
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        fn try_os_new(dest: &mut [u8]) -> Result<OsRng, Error>
        {
            let mut rng = OsRng::new()?;
            rng.try_fill_bytes(dest)?;
            Ok(rng)
        }

        fn try_jitter_new(dest: &mut [u8]) -> Result<JitterRng, Error>
        {
            let mut rng = JitterRng::new()?;
            rng.try_fill_bytes(dest)?;
            Ok(rng)
        }

        let mut switch_rng = None;
        match self.rng {
            EntropySource::None => {
                let os_rng_result = try_os_new(dest);
                match os_rng_result {
                    Ok(os_rng) => {
                        debug!("EntropyRng: using OsRng");
                        switch_rng = Some(EntropySource::Os(os_rng));
                    }
                    Err(os_rng_error) => {
                        warn!("EntropyRng: OsRng failed [falling back to JitterRng]: {}",
                              os_rng_error);
                        match try_jitter_new(dest) {
                            Ok(jitter_rng) => {
                                debug!("EntropyRng: using JitterRng");
                                switch_rng = Some(EntropySource::Jitter(jitter_rng));
                            }
                            Err(_jitter_error) => {
                                warn!("EntropyRng: JitterRng failed: {}",
                                      _jitter_error);
                                return Err(os_rng_error);
                            }
                        }
                    }
                }
            }
            EntropySource::Os(ref mut rng) => {
                let os_rng_result = rng.try_fill_bytes(dest);
                if let Err(os_rng_error) = os_rng_result {
                    warn!("EntropyRng: OsRng failed [falling back to JitterRng]: {}",
                          os_rng_error);
                    match try_jitter_new(dest) {
                        Ok(jitter_rng) => {
                            debug!("EntropyRng: using JitterRng");
                            switch_rng = Some(EntropySource::Jitter(jitter_rng));
                        }
                        Err(_jitter_error) => {
                            warn!("EntropyRng: JitterRng failed: {}",
                                  _jitter_error);
                            return Err(os_rng_error);
                        }
                    }
                }
            }
            EntropySource::Jitter(ref mut rng) => {
                if let Ok(os_rng) = try_os_new(dest) {
                    debug!("EntropyRng: using OsRng");
                    switch_rng = Some(EntropySource::Os(os_rng));
                } else {
                    return rng.try_fill_bytes(dest); // use JitterRng
                }
            }
        }
        if let Some(rng) = switch_rng {
            self.rng = rng;
        }
        Ok(())
    }
}

impl CryptoRng for EntropyRng {}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_entropy() {
        let mut rng = EntropyRng::new();
        let n = (rng.next_u32() ^ rng.next_u32()).count_ones();
        assert!(n >= 2);    // p(failure) approx 1e-7
    }
}
