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