diff --git a/benches/distributions.rs b/benches/distributions.rs index 568d5024992..4d93d9bd5ee 100644 --- a/benches/distributions.rs +++ b/benches/distributions.rs @@ -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); diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs index 3ff5700a376..be381c1fae7 100644 --- a/src/distributions/mod.rs +++ b/src/distributions/mod.rs @@ -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}; diff --git a/src/distributions/other.rs b/src/distributions/other.rs index 873043addac..1a5568322b4 100644 --- a/src/distributions/other.rs +++ b/src/distributions/other.rs @@ -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 for Uniform { #[inline] fn sample(&self, rng: &mut R) -> char { @@ -32,6 +57,22 @@ impl Distribution for Uniform { } } +impl Distribution for Alphanumeric { + fn sample(&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 for Uniform { #[inline] fn sample(&self, rng: &mut R) -> bool { @@ -118,6 +159,7 @@ impl Distribution> for Uniform where Uniform: Distribution { #[cfg(test)] mod tests { use {Rng, RngCore, Uniform}; + #[cfg(all(not(feature="std"), feature="alloc"))] use alloc::String; #[test] fn test_misc() { @@ -126,4 +168,19 @@ mod tests { rng.sample::(Uniform); rng.sample::(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); + } } diff --git a/src/lib.rs b/src/lib.rs index caf3fe73986..37cea0b58ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 } } @@ -871,10 +874,13 @@ impl Iterator for Generator where Uniform: Distribution /// [`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 { rng: R, } +#[allow(deprecated)] impl Iterator for AsciiGenerator { type Item = char; @@ -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);