linera_views/
random.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4#[cfg(target_arch = "wasm32")]
5use std::sync::{Mutex, MutexGuard, OnceLock};
6
7use rand::{rngs::SmallRng, Rng, SeedableRng};
8
9// The following seed is chosen to have equal numbers of 1s and 0s, as advised by
10// https://docs.rs/rand/latest/rand/rngs/struct.SmallRng.html
11// Specifically, it's "01" × 32 in binary
12const RNG_SEED: u64 = 6148914691236517205;
13
14/// A deterministic RNG.
15pub type DeterministicRng = SmallRng;
16
17/// A RNG that is non-deterministic if the platform supports it.
18#[cfg(not(target_arch = "wasm32"))]
19pub type NonDeterministicRng = rand::rngs::ThreadRng;
20/// A RNG that is non-deterministic if the platform supports it.
21#[cfg(target_arch = "wasm32")]
22pub type NonDeterministicRng = MutexGuard<'static, DeterministicRng>;
23
24/// Returns a deterministic RNG for testing.
25pub fn make_deterministic_rng() -> DeterministicRng {
26    SmallRng::seed_from_u64(RNG_SEED)
27}
28
29/// Returns a non-deterministic RNG where supported.
30pub fn make_nondeterministic_rng() -> NonDeterministicRng {
31    #[cfg(target_arch = "wasm32")]
32    {
33        static RNG: OnceLock<Mutex<SmallRng>> = OnceLock::new();
34        RNG.get_or_init(|| Mutex::new(make_deterministic_rng()))
35            .lock()
36            .expect("failed to lock RNG mutex")
37    }
38
39    #[cfg(not(target_arch = "wasm32"))]
40    {
41        rand::thread_rng()
42    }
43}
44
45/// Get a random alphanumeric string that can be used for all tests.
46pub fn generate_random_alphanumeric_string(length: usize, charset: &[u8]) -> String {
47    (0..length)
48        .map(|_| {
49            let random_index = make_nondeterministic_rng().gen_range(0..charset.len());
50            charset[random_index] as char
51        })
52        .collect()
53}
54
55/// Returns a unique namespace for testing.
56pub fn generate_test_namespace() -> String {
57    // Define the characters that are allowed in the alphanumeric string
58    let charset: &[u8] = b"0123456789abcdefghijklmnopqrstuvwxyz";
59    let entry = generate_random_alphanumeric_string(20, charset);
60    let namespace = format!("table_{}", entry);
61    tracing::warn!("Generating namespace={}", namespace);
62    namespace
63}