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