Skip to content

Commit 662c68a

Browse files
authored
Merge pull request #279 from dhardy/alpha
Add Alphanumeric distribution
2 parents f7a1038 + 5bc4785 commit 662c68a

File tree

4 files changed

+65
-8
lines changed

4 files changed

+65
-8
lines changed

benches/distributions.rs

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ distr!(distr_uniform_i64, i64, Uniform);
5050
distr!(distr_uniform_i128, i128, Uniform);
5151

5252
distr!(distr_uniform_bool, bool, Uniform);
53+
distr!(distr_uniform_alphanumeric, char, Alphanumeric);
5354
distr!(distr_uniform_codepoint, char, Uniform);
5455

5556
distr!(distr_uniform01_float32, f32, Uniform);

src/distributions/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Rng;
1919

2020
pub use self::float::{Open01, Closed01};
21+
pub use self::other::Alphanumeric;
2122
pub use self::range::Range;
2223
#[cfg(feature="std")]
2324
pub use self::gamma::{Gamma, ChiSquared, FisherF, StudentT};

src/distributions/other.rs

+57
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,31 @@ use core::char;
1515
use {Rng};
1616
use distributions::{Distribution, Uniform};
1717

18+
// ----- Sampling distributions -----
19+
20+
/// Sample a `char`, uniformly distributed over ASCII letters and numbers:
21+
/// a-z, A-Z and 0-9.
22+
///
23+
/// # Example
24+
///
25+
/// ```rust
26+
/// use std::iter;
27+
/// use rand::{Rng, thread_rng};
28+
/// use rand::distributions::Alphanumeric;
29+
///
30+
/// let mut rng = thread_rng();
31+
/// let chars: String = iter::repeat(())
32+
/// .map(|()| rng.sample(Alphanumeric))
33+
/// .take(7)
34+
/// .collect();
35+
/// println!("Random chars: {}", chars);
36+
/// ```
37+
#[derive(Debug)]
38+
pub struct Alphanumeric;
39+
40+
41+
// ----- Implementations of distributions -----
42+
1843
impl Distribution<char> for Uniform {
1944
#[inline]
2045
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
@@ -32,6 +57,22 @@ impl Distribution<char> for Uniform {
3257
}
3358
}
3459

60+
impl Distribution<char> for Alphanumeric {
61+
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
62+
const RANGE: u32 = 26 + 26 + 10;
63+
const GEN_ASCII_STR_CHARSET: &'static [u8] =
64+
b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
65+
abcdefghijklmnopqrstuvwxyz\
66+
0123456789";
67+
loop {
68+
let var = rng.next_u32() >> 26;
69+
if var < RANGE {
70+
return GEN_ASCII_STR_CHARSET[var as usize] as char
71+
}
72+
}
73+
}
74+
}
75+
3576
impl Distribution<bool> for Uniform {
3677
#[inline]
3778
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
@@ -118,6 +159,7 @@ impl<T> Distribution<Option<T>> for Uniform where Uniform: Distribution<T> {
118159
#[cfg(test)]
119160
mod tests {
120161
use {Rng, RngCore, Uniform};
162+
#[cfg(all(not(feature="std"), feature="alloc"))] use alloc::String;
121163

122164
#[test]
123165
fn test_misc() {
@@ -126,4 +168,19 @@ mod tests {
126168
rng.sample::<char, _>(Uniform);
127169
rng.sample::<bool, _>(Uniform);
128170
}
171+
172+
#[cfg(any(feature="std", feature="alloc"))]
173+
#[test]
174+
fn test_chars() {
175+
use core::iter;
176+
use distributions::Alphanumeric;
177+
let mut rng = ::test::rng(805);
178+
179+
let c = rng.sample(Alphanumeric);
180+
assert!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
181+
182+
let word: String = iter::repeat(())
183+
.map(|()| rng.sample(Alphanumeric)).take(5).collect();
184+
assert_eq!(word.len(), 5);
185+
}
129186
}

src/lib.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -652,11 +652,14 @@ pub trait Rng: RngCore + Sized {
652652
/// # Example
653653
///
654654
/// ```rust
655+
/// #[allow(deprecated)]
655656
/// use rand::{thread_rng, Rng};
656657
///
657658
/// let s: String = thread_rng().gen_ascii_chars().take(10).collect();
658659
/// println!("{}", s);
659660
/// ```
661+
#[allow(deprecated)]
662+
#[deprecated(since="0.5.0", note="use distributions::Alphanumeric instead")]
660663
fn gen_ascii_chars(&mut self) -> AsciiGenerator<&mut Self> {
661664
AsciiGenerator { rng: self }
662665
}
@@ -871,10 +874,13 @@ impl<T, R: RngCore> Iterator for Generator<T, R> where Uniform: Distribution<T>
871874
/// [`gen_ascii_chars`]: trait.Rng.html#method.gen_ascii_chars
872875
/// [`Rng`]: trait.Rng.html
873876
#[derive(Debug)]
877+
#[allow(deprecated)]
878+
#[deprecated(since="0.5.0", note="use distributions::Alphanumeric instead")]
874879
pub struct AsciiGenerator<R: RngCore> {
875880
rng: R,
876881
}
877882

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

@@ -1206,14 +1212,6 @@ mod test {
12061212
assert_eq!(r.gen_weighted_bool(1), true);
12071213
}
12081214

1209-
#[test]
1210-
fn test_gen_ascii_str() {
1211-
let mut r = rng(105);
1212-
assert_eq!(r.gen_ascii_chars().take(0).count(), 0);
1213-
assert_eq!(r.gen_ascii_chars().take(10).count(), 10);
1214-
assert_eq!(r.gen_ascii_chars().take(16).count(), 16);
1215-
}
1216-
12171215
#[test]
12181216
fn test_gen_vec() {
12191217
let mut r = rng(106);

0 commit comments

Comments
 (0)