1use rand::RngCore;
4
5use crate::{Felt, Word};
6
7mod coin;
8pub use coin::RandomCoin;
9
10#[cfg(any(test, feature = "std"))]
12pub mod test_utils;
13
14pub trait Randomizable: Sized {
19 const VALUE_SIZE: usize;
24
25 fn from_random_bytes(source: &[u8]) -> Option<Self>;
27}
28
29impl Randomizable for u128 {
30 const VALUE_SIZE: usize = 16;
31
32 fn from_random_bytes(source: &[u8]) -> Option<Self> {
33 if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
34 Some(u128::from_le_bytes(bytes))
35 } else {
36 None
37 }
38 }
39}
40
41impl Randomizable for u64 {
42 const VALUE_SIZE: usize = 8;
43
44 fn from_random_bytes(source: &[u8]) -> Option<Self> {
45 if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
46 Some(u64::from_le_bytes(bytes))
47 } else {
48 None
49 }
50 }
51}
52
53impl Randomizable for u32 {
54 const VALUE_SIZE: usize = 4;
55
56 fn from_random_bytes(source: &[u8]) -> Option<Self> {
57 if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
58 Some(u32::from_le_bytes(bytes))
59 } else {
60 None
61 }
62 }
63}
64
65impl Randomizable for u16 {
66 const VALUE_SIZE: usize = 2;
67
68 fn from_random_bytes(source: &[u8]) -> Option<Self> {
69 if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
70 Some(u16::from_le_bytes(bytes))
71 } else {
72 None
73 }
74 }
75}
76
77impl Randomizable for u8 {
78 const VALUE_SIZE: usize = 1;
79
80 fn from_random_bytes(source: &[u8]) -> Option<Self> {
81 Some(source[0])
82 }
83}
84
85impl Randomizable for Felt {
86 const VALUE_SIZE: usize = 8;
87
88 fn from_random_bytes(source: &[u8]) -> Option<Self> {
89 if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
90 let value = u64::from_le_bytes(bytes);
91 if value < Felt::ORDER {
93 Some(Felt::new_unchecked(value))
94 } else {
95 None
96 }
97 } else {
98 None
99 }
100 }
101}
102
103impl Randomizable for Word {
104 const VALUE_SIZE: usize = Word::SERIALIZED_SIZE;
105
106 fn from_random_bytes(bytes: &[u8]) -> Option<Self> {
107 let bytes_array: Option<[u8; 32]> = bytes.try_into().ok();
108 if let Some(bytes_array) = bytes_array {
109 Self::try_from(bytes_array).ok()
110 } else {
111 None
112 }
113 }
114}
115
116impl<const N: usize> Randomizable for [u8; N] {
117 const VALUE_SIZE: usize = N;
118
119 fn from_random_bytes(source: &[u8]) -> Option<Self> {
120 let mut result = [Default::default(); N];
121 result.copy_from_slice(source);
122
123 Some(result)
124 }
125}
126
127pub trait FeltRng: RngCore {
131 fn draw_element(&mut self) -> Felt;
133
134 fn draw_word(&mut self) -> Word;
136}
137
138#[cfg(feature = "std")]
145pub fn random_felt() -> Felt {
146 use rand::Rng;
147 let mut rng = rand::rng();
148 loop {
151 if let Ok(felt) = Felt::new(rng.random::<u64>()) {
152 return felt;
153 }
154 }
155}
156
157#[cfg(feature = "std")]
161pub fn random_word() -> Word {
162 Word::new([random_felt(), random_felt(), random_felt(), random_felt()])
163}