#[cfg(feature = "thread_safe")]
use crate::error::Result;
#[cfg(feature = "thread_safe")]
use crate::traits::Rng;
#[cfg(feature = "thread_safe")]
use std::sync::{Arc, Mutex, RwLock};
#[cfg(feature = "thread_safe")]
pub struct ThreadSafeRng<T> {
inner: Arc<Mutex<T>>,
}
#[cfg(feature = "thread_safe")]
impl<T: Rng> ThreadSafeRng<T> {
pub fn new(rng: T) -> Self {
Self {
inner: Arc::new(Mutex::new(rng)),
}
}
pub fn next_u32(&self) -> u32 {
let mut rng = self.inner.lock().unwrap();
rng.next_u32()
}
pub fn next_u64(&self) -> u64 {
let mut rng = self.inner.lock().unwrap();
rng.next_u64()
}
pub fn fill_bytes(&self, dest: &mut [u8]) {
let mut rng = self.inner.lock().unwrap();
rng.fill_bytes(dest);
}
}
#[cfg(feature = "thread_safe")]
impl<T: Rng> Rng for ThreadSafeRng<T> {
fn next_u32(&mut self) -> u32 {
ThreadSafeRng::next_u32(self)
}
fn next_u64(&mut self) -> u64 {
ThreadSafeRng::next_u64(self)
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
ThreadSafeRng::fill_bytes(self, dest);
}
}
#[cfg(feature = "thread_safe")]
impl<T> Clone for ThreadSafeRng<T> {
fn clone(&self) -> Self {
Self {
inner: Arc::clone(&self.inner),
}
}
}
#[cfg(all(feature = "thread_safe", feature = "fork_safe"))]
pub struct ForkSafeRng<T> {
inner: Arc<RwLock<T>>,
block_hashes: Arc<RwLock<Vec<[u8; 32]>>>,
fork_history_size: usize,
}
#[cfg(all(feature = "thread_safe", feature = "fork_safe"))]
impl<T: crate::traits::SeedableRng<Seed = crate::seed::Seed>> ForkSafeRng<T> {
pub fn new(rng: T, fork_history_size: usize) -> Self {
Self {
inner: Arc::new(RwLock::new(rng)),
block_hashes: Arc::new(RwLock::new(Vec::new())),
fork_history_size,
}
}
pub fn check_fork(&self, current_hash: &[u8; 32]) -> Result<bool> {
let mut hashes = self.block_hashes.write().unwrap();
if let Some(last_hash) = hashes.last()
&& last_hash == current_hash
{
return Ok(false); }
hashes.push(*current_hash);
if hashes.len() > self.fork_history_size {
hashes.remove(0);
}
let seed = crate::seed::Seed::from_block_hash(current_hash)?;
let mut rng = self.inner.write().unwrap();
rng.reseed(seed)?;
Ok(true) }
}
#[cfg(all(feature = "thread_safe", feature = "fork_safe"))]
impl<T: Rng> Rng for ForkSafeRng<T> {
fn next_u32(&mut self) -> u32 {
let mut rng = self.inner.write().unwrap();
rng.next_u32()
}
fn next_u64(&mut self) -> u64 {
let mut rng = self.inner.write().unwrap();
rng.next_u64()
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
let mut rng = self.inner.write().unwrap();
rng.fill_bytes(dest);
}
}
#[cfg(feature = "std")]
pub struct GlobalRng {
}
#[cfg(feature = "std")]
impl GlobalRng {
pub fn thread_rng() -> Self {
Self {}
}
}
#[cfg(feature = "std")]
impl Rng for GlobalRng {
fn next_u32(&mut self) -> u32 {
0 }
fn next_u64(&mut self) -> u64 {
0 }
fn fill_bytes(&mut self, _dest: &mut [u8]) {
}
}