buf_rand/lib.rs
1use rand::RngCore;
2
3/// used to generate random booleans using a bit buffer
4pub struct BufRand<R: RngCore> {
5 /// this is a buffer of bits for random booleans
6 bit_buf: u64,
7 /// this indicates how many bits have been read from `bit_buf`.
8 /// `bit_buf` is not simply checked against 0 to prevent slight bias to
9 /// true
10 shift_counter: u8,
11 /// the inner randomizer of this BufRand. this is pub so it can be used
12 /// after this BufRand has been Constructed
13 pub rand: R,
14}
15
16impl<R: RngCore> BufRand<R> {
17 /// create a new `BufRand` which generates random booleans using the
18 /// supplied rng
19 pub fn new(rand: R) -> Self {
20 BufRand {
21 bit_buf: 0,
22 shift_counter: 0xff, // not initialized with 0 to prevent bit_buf from being all 0
23 rand,
24 }
25 }
26
27 /// returns a random boolean from the buffer of this `BufRand`
28 /// ```
29 /// use buf_rand::BufRand;
30 ///
31 /// let mut rand = BufRand::new(rand::thread_rng());
32 /// rand.next_bool();
33 /// ```
34 pub fn next_bool(&mut self) -> bool {
35 if self.shift_counter >= 64 {
36 self.bit_buf = self.rand.next_u64();
37 self.shift_counter = 0;
38 }
39 let out = self.bit_buf % 2 == 0;
40 self.bit_buf >>= 1;
41 self.shift_counter += 1;
42 out
43 }
44
45 /// randomizes the capitalization of a char
46 /// this returns a `String` since some chars may result in multiple when the
47 /// case is changed such as this
48 /// ```
49 /// // example of character turning into multiple
50 /// assert_eq!('ß'.to_uppercase().to_string(), "SS");
51 /// use buf_rand::BufRand;
52 ///
53 /// let mut rand = BufRand::new(rand::thread_rng());
54 /// rand.rand_char_case(&'E');
55 /// ```
56 pub fn rand_char_case(&mut self, c: &char) -> String {
57 if self.next_bool() {
58 c.to_uppercase().to_string()
59 } else {
60 c.to_lowercase().to_string()
61 }
62 }
63
64 /// randomizes the capitalization of every character in the string
65 /// ```
66 /// use buf_rand::BufRand;
67 ///
68 /// let mut rand = BufRand::new(rand::thread_rng());
69 /// rand.rand_string_case("hello world!");
70 /// ```
71 pub fn rand_string_case(&mut self, s: &str) -> String {
72 s.chars()
73 .into_iter()
74 .map(|c| self.rand_char_case(&c))
75 .collect()
76 }
77}