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
//! This crates contains functions for generating random values.
//!
//! These functions are intended to be used in tests, benchmarks, and examples. When compiled to
//! WebAssembly target, all of the functions are omitted.

pub use internal::*;

#[cfg(not(target_family = "wasm"))]
mod internal {
    use core::{convert::TryInto, fmt::Debug};
    use rand::prelude::*;
    use utils::Randomizable;

    // RANDOM VALUE GENERATION
    // ============================================================================================

    /// Returns a single random value of the specified type.
    ///
    /// # Panics
    /// Panics if:
    /// * A valid value requires at over 32 bytes.
    /// * A valid value could not be generated after 100 tries.
    pub fn rand_value<R: Randomizable>() -> R {
        for _ in 0..100 {
            let bytes = rand::thread_rng().gen::<[u8; 32]>();
            if let Some(value) = R::from_random_bytes(&bytes[..R::VALUE_SIZE]) {
                return value;
            }
        }

        panic!("failed generate a random field element");
    }

    /// Returns a vector of random value of the specified type and the specified length.
    ///
    /// # Panics
    /// Panics if:
    /// * A valid value requires at over 32 bytes.
    /// * A valid value could not be generated after 100 tries.
    pub fn rand_vector<R: Randomizable>(n: usize) -> Vec<R> {
        let mut result = Vec::with_capacity(n);
        let seed = rand::thread_rng().gen::<[u8; 32]>();
        let mut g = StdRng::from_seed(seed);
        for _ in 0..100 * n {
            let bytes = g.gen::<[u8; 32]>();
            if let Some(element) = R::from_random_bytes(&bytes[..R::VALUE_SIZE]) {
                result.push(element);
                if result.len() == n {
                    return result;
                }
            }
        }

        panic!("failed to generate enough random field elements");
    }

    /// Returns an array of random value of the specified type and the specified length.
    ///
    /// # Panics
    /// Panics if:
    /// * A valid value requires at over 32 bytes.
    /// * A valid value could not be generated after 100 tries.
    pub fn rand_array<R: Randomizable + Debug, const N: usize>() -> [R; N] {
        let elements = rand_vector(N);
        elements
            .try_into()
            .expect("failed to convert vector to array")
    }

    /// Returns a vector of value of the specified type and the specified length generated
    /// pseudo-randomly from the specified `seed`.
    ///
    /// # Panics
    /// Panics if:
    /// * A valid value requires at over 32 bytes.
    /// * A valid value could not be generated after 100 tries.
    pub fn prng_vector<R: Randomizable>(seed: [u8; 32], n: usize) -> Vec<R> {
        let mut result = Vec::with_capacity(n);
        let mut g = StdRng::from_seed(seed);
        for _ in 0..100 * n {
            let bytes = g.gen::<[u8; 32]>();
            if let Some(element) = R::from_random_bytes(&bytes[..R::VALUE_SIZE]) {
                result.push(element);
                if result.len() == n {
                    return result;
                }
            }
        }

        panic!("failed to generate enough random field elements");
    }

    /// Returns an array of value of the specified type and the specified length generated
    /// pseudo-randomly from the specified `seed`.
    ///
    /// # Panics
    /// Panics if:
    /// * A valid value requires at over 32 bytes.
    /// * A valid value could not be generated after 100 tries.
    pub fn prng_array<R: Randomizable + Debug, const N: usize>(seed: [u8; 32]) -> [R; N] {
        let elements = prng_vector(seed, N);
        elements
            .try_into()
            .expect("failed to convert vector to array")
    }

    // SHUFFLING
    // ============================================================================================

    /// Randomly shuffles slice elements.
    pub fn shuffle<T>(values: &mut [T]) {
        values.shuffle(&mut thread_rng());
    }
}

#[cfg(target_family = "wasm")]
mod internal {}