Skip to content

Commit

Permalink
Merge pull request #279 from dhardy/alpha
Browse files Browse the repository at this point in the history
Add Alphanumeric distribution
  • Loading branch information
dhardy committed Mar 3, 2018
2 parents d8a63a1 + 3f0442f commit bea7ae3
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 8 deletions.
1 change: 1 addition & 0 deletions benches/distributions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ distr!(distr_uniform_i64, i64, Uniform);
distr!(distr_uniform_i128, i128, Uniform);

distr!(distr_uniform_bool, bool, Uniform);
distr!(distr_uniform_alphanumeric, char, Alphanumeric);
distr!(distr_uniform_codepoint, char, Uniform);

distr!(distr_uniform01_float32, f32, Uniform);
Expand Down
1 change: 1 addition & 0 deletions src/distributions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Rng;

pub use self::float::{Open01, Closed01};
pub use self::other::Alphanumeric;
pub use self::range::Range;
#[cfg(feature="std")]
pub use self::gamma::{Gamma, ChiSquared, FisherF, StudentT};
Expand Down
57 changes: 57 additions & 0 deletions src/distributions/other.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,31 @@ use core::char;
use {Rng};
use distributions::{Distribution, Uniform};

// ----- Sampling distributions -----

/// Sample a `char`, uniformly distributed over ASCII letters and numbers:
/// a-z, A-Z and 0-9.
///
/// # Example
///
/// ```rust
/// use std::iter;
/// use rand::{Rng, thread_rng};
/// use rand::distributions::Alphanumeric;
///
/// let mut rng = thread_rng();
/// let chars: String = iter::repeat(())
/// .map(|()| rng.sample(Alphanumeric))
/// .take(7)
/// .collect();
/// println!("Random chars: {}", chars);
/// ```
#[derive(Debug)]
pub struct Alphanumeric;


// ----- Implementations of distributions -----

impl Distribution<char> for Uniform {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
Expand All @@ -32,6 +57,22 @@ impl Distribution<char> for Uniform {
}
}

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: &'static [u8] =
b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789";
loop {
let var = rng.next_u32() >> 26;
if var < RANGE {
return GEN_ASCII_STR_CHARSET[var as usize] as char
}
}
}
}

impl Distribution<bool> for Uniform {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
Expand Down Expand Up @@ -118,6 +159,7 @@ impl<T> Distribution<Option<T>> for Uniform where Uniform: Distribution<T> {
#[cfg(test)]
mod tests {
use {Rng, RngCore, Uniform};
#[cfg(all(not(feature="std"), feature="alloc"))] use alloc::String;

#[test]
fn test_misc() {
Expand All @@ -126,4 +168,19 @@ mod tests {
rng.sample::<char, _>(Uniform);
rng.sample::<bool, _>(Uniform);
}

#[cfg(any(feature="std", feature="alloc"))]
#[test]
fn test_chars() {
use core::iter;
use distributions::Alphanumeric;
let mut rng = ::test::rng(805);

let c = rng.sample(Alphanumeric);
assert!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));

let word: String = iter::repeat(())
.map(|()| rng.sample(Alphanumeric)).take(5).collect();
assert_eq!(word.len(), 5);
}
}
14 changes: 6 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,11 +652,14 @@ pub trait Rng: RngCore + Sized {
/// # Example
///
/// ```rust
/// #[allow(deprecated)]
/// use rand::{thread_rng, Rng};
///
/// let s: String = thread_rng().gen_ascii_chars().take(10).collect();
/// println!("{}", s);
/// ```
#[allow(deprecated)]
#[deprecated(since="0.5.0", note="use distributions::Alphanumeric instead")]
fn gen_ascii_chars(&mut self) -> AsciiGenerator<&mut Self> {
AsciiGenerator { rng: self }
}
Expand Down Expand Up @@ -871,10 +874,13 @@ impl<T, R: RngCore> Iterator for Generator<T, R> where Uniform: Distribution<T>
/// [`gen_ascii_chars`]: trait.Rng.html#method.gen_ascii_chars
/// [`Rng`]: trait.Rng.html
#[derive(Debug)]
#[allow(deprecated)]
#[deprecated(since="0.5.0", note="use distributions::Alphanumeric instead")]
pub struct AsciiGenerator<R: RngCore> {
rng: R,
}

#[allow(deprecated)]
impl<R: RngCore> Iterator for AsciiGenerator<R> {
type Item = char;

Expand Down Expand Up @@ -1206,14 +1212,6 @@ mod test {
assert_eq!(r.gen_weighted_bool(1), true);
}

#[test]
fn test_gen_ascii_str() {
let mut r = rng(105);
assert_eq!(r.gen_ascii_chars().take(0).count(), 0);
assert_eq!(r.gen_ascii_chars().take(10).count(), 10);
assert_eq!(r.gen_ascii_chars().take(16).count(), 16);
}

#[test]
fn test_gen_vec() {
let mut r = rng(106);
Expand Down

0 comments on commit bea7ae3

Please sign in to comment.