Skip to main content

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}