use rand::RngCore;
use crate::{Felt, Word};
mod coin;
pub use coin::RandomCoin;
#[cfg(any(test, feature = "std"))]
pub mod test_utils;
pub trait Randomizable: Sized {
const VALUE_SIZE: usize;
fn from_random_bytes(source: &[u8]) -> Option<Self>;
}
impl Randomizable for u128 {
const VALUE_SIZE: usize = 16;
fn from_random_bytes(source: &[u8]) -> Option<Self> {
if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
Some(u128::from_le_bytes(bytes))
} else {
None
}
}
}
impl Randomizable for u64 {
const VALUE_SIZE: usize = 8;
fn from_random_bytes(source: &[u8]) -> Option<Self> {
if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
Some(u64::from_le_bytes(bytes))
} else {
None
}
}
}
impl Randomizable for u32 {
const VALUE_SIZE: usize = 4;
fn from_random_bytes(source: &[u8]) -> Option<Self> {
if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
Some(u32::from_le_bytes(bytes))
} else {
None
}
}
}
impl Randomizable for u16 {
const VALUE_SIZE: usize = 2;
fn from_random_bytes(source: &[u8]) -> Option<Self> {
if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
Some(u16::from_le_bytes(bytes))
} else {
None
}
}
}
impl Randomizable for u8 {
const VALUE_SIZE: usize = 1;
fn from_random_bytes(source: &[u8]) -> Option<Self> {
Some(source[0])
}
}
impl Randomizable for Felt {
const VALUE_SIZE: usize = 8;
fn from_random_bytes(source: &[u8]) -> Option<Self> {
if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
let value = u64::from_le_bytes(bytes);
if value < Felt::ORDER {
Some(Felt::new_unchecked(value))
} else {
None
}
} else {
None
}
}
}
impl Randomizable for Word {
const VALUE_SIZE: usize = Word::SERIALIZED_SIZE;
fn from_random_bytes(bytes: &[u8]) -> Option<Self> {
let bytes_array: Option<[u8; 32]> = bytes.try_into().ok();
if let Some(bytes_array) = bytes_array {
Self::try_from(bytes_array).ok()
} else {
None
}
}
}
impl<const N: usize> Randomizable for [u8; N] {
const VALUE_SIZE: usize = N;
fn from_random_bytes(source: &[u8]) -> Option<Self> {
let mut result = [Default::default(); N];
result.copy_from_slice(source);
Some(result)
}
}
pub trait FeltRng: RngCore {
fn draw_element(&mut self) -> Felt;
fn draw_word(&mut self) -> Word;
}
#[cfg(feature = "std")]
pub fn random_felt() -> Felt {
use rand::Rng;
let mut rng = rand::rng();
loop {
if let Ok(felt) = Felt::new(rng.random::<u64>()) {
return felt;
}
}
}
#[cfg(feature = "std")]
pub fn random_word() -> Word {
Word::new([random_felt(), random_felt(), random_felt(), random_felt()])
}