ic_canister_kit/number/
random.rs1use crate::canister::types::CanisterCallResult;
4
5#[inline]
8pub async fn random() -> CanisterCallResult<[u8; 32]> {
9 let call_result = ic_cdk_management_canister::raw_rand().await;
10
11 let random = call_result.map_err(|err| crate::canister::types::CanisterCallError {
12 canister_id: crate::identity::CanisterId::management_canister(),
13 method: "ic#raw_rand".to_string(),
14 message: err.to_string(),
15 })?;
16
17 let mut data = [0; 32];
18
19 data[..32].copy_from_slice(&random[..32]);
20
21 Ok(data)
22}
23
24#[derive(Debug)]
30pub struct RandomGenerator {
31 random: [u8; 32],
32 current: u8,
33}
34
35impl RandomGenerator {
36 pub fn new() -> Self {
38 RandomGenerator {
39 random: [0; 32],
40 current: 32,
41 }
42 }
43 pub async fn next(&mut self, number: usize) -> CanisterCallResult<Vec<u8>> {
45 let mut data = Vec::with_capacity(number);
46 let mut remain = number;
47
48 while remain > 32 {
50 data.extend_from_slice(&random().await?);
51 remain -= 32;
52 }
53
54 let available = 32 - self.current as usize;
55 if remain <= available {
56 let current = self.current as usize;
57 data.extend_from_slice(&self.random[current..current + remain]);
58 self.current += remain as u8;
59 } else {
60 let current = self.current as usize;
62 data.extend_from_slice(&self.random[current..current + available]);
63 remain -= available;
64
65 self.random = random().await?;
67 self.current = 0;
68
69 data.extend_from_slice(&self.random[0..remain]);
71 self.current += remain as u8;
72 }
73
74 Ok(data)
75 }
76}
77
78impl Default for RandomGenerator {
79 fn default() -> Self {
80 Self::new()
81 }
82}