loro_fractional_index/
jitter.rs

1use std::sync::Arc;
2
3use crate::{new_after, new_before, new_between, FractionalIndex, TERMINATOR};
4use rand::Rng;
5
6impl FractionalIndex {
7    pub fn jitter_default(rng: &mut impl Rng, jitter: u8) -> Self {
8        Self::jitter(Vec::new(), rng, jitter)
9    }
10
11    pub fn new_jitter<R: Rng>(
12        lower: Option<&FractionalIndex>,
13        upper: Option<&FractionalIndex>,
14        rng: &mut R,
15        jitter: u8,
16    ) -> Option<Self> {
17        match (lower, upper) {
18            (Some(lower), Some(upper)) => Self::new_between_jitter(lower, upper, rng, jitter),
19            (Some(lower), None) => Self::new_after_jitter(lower, rng, jitter).into(),
20            (None, Some(upper)) => Self::new_before_jitter(upper, rng, jitter).into(),
21            (None, None) => FractionalIndex::jitter_default(rng, jitter).into(),
22        }
23    }
24
25    fn jitter<R: Rng>(mut bytes: Vec<u8>, rng: &mut R, jitter: u8) -> FractionalIndex {
26        bytes.push(TERMINATOR);
27        bytes.extend((0..jitter).map(|_| rng.gen::<u8>()));
28        FractionalIndex(Arc::new(bytes))
29    }
30
31    pub fn new_before_jitter<R: Rng>(
32        FractionalIndex(bytes): &FractionalIndex,
33        rng: &mut R,
34        jitter: u8,
35    ) -> Self {
36        Self::jitter(new_before(bytes), rng, jitter)
37    }
38
39    pub fn new_after_jitter<R: Rng>(
40        FractionalIndex(bytes): &FractionalIndex,
41        rng: &mut R,
42        jitter: u8,
43    ) -> Self {
44        Self::jitter(new_after(bytes), rng, jitter)
45    }
46
47    pub fn new_between_jitter<R: Rng>(
48        FractionalIndex(left): &FractionalIndex,
49        FractionalIndex(right): &FractionalIndex,
50        rng: &mut R,
51        jitter: u8,
52    ) -> Option<Self> {
53        new_between(left, right, jitter as usize + 1).map(|x| Self::jitter(x, rng, jitter))
54    }
55
56    pub fn generate_n_evenly_jitter<R: Rng>(
57        lower: Option<&FractionalIndex>,
58        upper: Option<&FractionalIndex>,
59        n: usize,
60        rng: &mut R,
61        jitter: u8,
62    ) -> Option<Vec<Self>> {
63        fn generate(
64            lower: Option<&FractionalIndex>,
65            upper: Option<&FractionalIndex>,
66            n: usize,
67            push: &mut impl FnMut(FractionalIndex),
68            rng: &mut impl Rng,
69            jitter: u8,
70        ) {
71            if n == 0 {
72                return;
73            }
74
75            let mid = n / 2;
76            let mid_ans = FractionalIndex::new_jitter(lower, upper, rng, jitter).unwrap();
77            if n == 1 {
78                push(mid_ans);
79                return;
80            }
81
82            generate(lower, Some(&mid_ans), mid, push, rng, jitter);
83            push(mid_ans.clone());
84            if n - mid - 1 == 0 {
85                return;
86            }
87            generate(Some(&mid_ans), upper, n - mid - 1, push, rng, jitter);
88        }
89
90        if n == 0 {
91            return Some(Vec::new());
92        }
93
94        match (lower, upper) {
95            (Some(a), Some(b)) if a >= b => return None,
96            _ => {}
97        }
98
99        let mut ans = Vec::with_capacity(n);
100        generate(lower, upper, n, &mut |v| ans.push(v), rng, jitter);
101        Some(ans)
102    }
103}