use core::char;
use core::num::Wrapping;
use crate::{Rng};
use crate::distributions::{Distribution, Standard, Uniform};
#[derive(Debug)]
pub struct Alphanumeric;
impl Distribution<char> for Standard {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
const GAP_SIZE: u32 = 0xDFFF - 0xD800 + 1;
let range = Uniform::new(GAP_SIZE, 0x11_0000);
let mut n = range.sample(rng);
if n <= 0xDFFF {
n -= GAP_SIZE;
}
unsafe { char::from_u32_unchecked(n) }
}
}
impl Distribution<char> for Alphanumeric {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
const RANGE: u32 = 26 + 26 + 10;
const GEN_ASCII_STR_CHARSET: &[u8] =
b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789";
loop {
let var = rng.next_u32() >> (32 - 6);
if var < RANGE {
return GEN_ASCII_STR_CHARSET[var as usize] as char
}
}
}
}
impl Distribution<bool> for Standard {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
(rng.next_u32() as i32) < 0
}
}
macro_rules! tuple_impl {
($($tyvar:ident),* ) => {
impl< $( $tyvar ),* >
Distribution<( $( $tyvar ),* , )>
for Standard
where $( Standard: Distribution<$tyvar> ),*
{
#[inline]
fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> ( $( $tyvar ),* , ) {
(
$(
_rng.gen::<$tyvar>()
),*
,
)
}
}
}
}
impl Distribution<()> for Standard {
#[inline]
fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L}
macro_rules! array_impl {
{$n:expr, $t:ident, $($ts:ident,)*} => {
array_impl!{($n - 1), $($ts,)*}
impl<T> Distribution<[T; $n]> for Standard where Standard: Distribution<T> {
#[inline]
fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] {
[_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*]
}
}
};
{$n:expr,} => {
impl<T> Distribution<[T; $n]> for Standard {
fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] { [] }
}
};
}
array_impl!{32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}
impl<T> Distribution<Option<T>> for Standard where Standard: Distribution<T> {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<T> {
if rng.gen::<bool>() {
Some(rng.gen())
} else {
None
}
}
}
impl<T> Distribution<Wrapping<T>> for Standard where Standard: Distribution<T> {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Wrapping<T> {
Wrapping(rng.gen())
}
}
#[cfg(test)]
mod tests {
use crate::{Rng, RngCore, Standard};
use crate::distributions::Alphanumeric;
#[cfg(all(not(feature="std"), feature="alloc"))] use alloc::string::String;
#[test]
fn test_misc() {
let rng: &mut dyn RngCore = &mut crate::test::rng(820);
rng.sample::<char, _>(Standard);
rng.sample::<bool, _>(Standard);
}
#[cfg(feature="alloc")]
#[test]
fn test_chars() {
use core::iter;
let mut rng = crate::test::rng(805);
let word: String = iter::repeat(())
.map(|()| rng.gen::<char>()).take(1000).collect();
assert!(word.len() != 0);
}
#[test]
fn test_alphanumeric() {
let mut rng = crate::test::rng(806);
let mut incorrect = false;
for _ in 0..100 {
let c = rng.sample(Alphanumeric);
incorrect |= !((c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') );
}
assert!(incorrect == false);
}
}