util.rs

 1use rand::prelude::*;
 2use std::cmp::Ordering;
 3
 4pub fn post_inc(value: &mut usize) -> usize {
 5    let prev = *value;
 6    *value += 1;
 7    prev
 8}
 9
10pub fn find_insertion_index<'a, F, T, E>(slice: &'a [T], mut f: F) -> Result<usize, E>
11where
12    F: FnMut(&'a T) -> Result<Ordering, E>,
13{
14    use Ordering::*;
15
16    let s = slice;
17    let mut size = s.len();
18    if size == 0 {
19        return Ok(0);
20    }
21    let mut base = 0usize;
22    while size > 1 {
23        let half = size / 2;
24        let mid = base + half;
25        // mid is always in [0, size), that means mid is >= 0 and < size.
26        // mid >= 0: by definition
27        // mid < size: mid = size / 2 + size / 4 + size / 8 ...
28        let cmp = f(unsafe { s.get_unchecked(mid) })?;
29        base = if cmp == Greater { base } else { mid };
30        size -= half;
31    }
32    // base is always in [0, size) because base <= mid.
33    let cmp = f(unsafe { s.get_unchecked(base) })?;
34    if cmp == Equal {
35        Ok(base)
36    } else {
37        Ok(base + (cmp == Less) as usize)
38    }
39}
40
41pub struct RandomCharIter<T: Rng>(T);
42
43impl<T: Rng> RandomCharIter<T> {
44    pub fn new(rng: T) -> Self {
45        Self(rng)
46    }
47}
48
49impl<T: Rng> Iterator for RandomCharIter<T> {
50    type Item = char;
51
52    fn next(&mut self) -> Option<Self::Item> {
53        if self.0.gen_bool(1.0 / 5.0) {
54            Some('\n')
55        } else {
56            Some(self.0.gen_range(b'a'..b'z' + 1).into())
57        }
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn test_find_insertion_index() {
67        assert_eq!(
68            find_insertion_index(&[0, 4, 8], |probe| Ok::<Ordering, ()>(probe.cmp(&2))),
69            Ok(1)
70        );
71    }
72}