wasmcloud_component/wrappers/
random.rs

1#[cfg(feature = "rand")]
2pub use rand::{Rng, RngCore};
3
4#[cfg(feature = "uuid")]
5pub use uuid::Uuid;
6
7pub struct HostRng;
8
9impl HostRng {
10    /// Generate a 32-bit random number
11    #[inline]
12    #[must_use]
13    pub fn random32() -> u32 {
14        ::wasi::random::random::get_random_u64() as _
15    }
16
17    /// Generate a v4-format guid in the form "nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn"
18    /// where n is a lowercase hex digit and all bits are random.
19    #[cfg(feature = "uuid")]
20    #[must_use]
21    pub fn generate_guid() -> Uuid {
22        let buf = uuid::Bytes::try_from(::wasi::random::random::get_random_bytes(16))
23            .expect("invalid amount of bytes generated");
24        uuid::Builder::from_random_bytes(buf).into_uuid()
25    }
26
27    /// Generate a random integer within an inclusive range. ( min <= n <= max )
28    #[cfg(feature = "rand")]
29    #[must_use]
30    pub fn random_in_range(min: u32, max: u32) -> u32 {
31        HostRng.gen_range(min..=max)
32    }
33}
34
35#[cfg(feature = "rand")]
36impl crate::RngCore for HostRng {
37    #[inline]
38    fn next_u32(&mut self) -> u32 {
39        HostRng::random32()
40    }
41
42    #[inline]
43    fn next_u64(&mut self) -> u64 {
44        ::wasi::random::random::get_random_u64()
45    }
46
47    fn fill_bytes(&mut self, dest: &mut [u8]) {
48        let n = dest.len();
49        if usize::BITS <= u64::BITS || n <= u64::MAX as _ {
50            dest.copy_from_slice(&::wasi::random::random::get_random_bytes(n as _));
51        } else {
52            let (head, tail) = dest.split_at_mut(u64::MAX as _);
53            head.copy_from_slice(&::wasi::random::random::get_random_bytes(u64::MAX));
54            // TODO: Optimize
55            self.fill_bytes(tail);
56        }
57    }
58
59    #[inline]
60    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
61        self.fill_bytes(dest);
62        Ok(())
63    }
64}