locator.rs

 1use lazy_static::lazy_static;
 2use smallvec::{smallvec, SmallVec};
 3use std::iter;
 4
 5lazy_static! {
 6    pub static ref MIN: Locator = Locator::min();
 7    pub static ref MAX: Locator = Locator::max();
 8}
 9
10#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct Locator(SmallVec<[u64; 4]>);
12
13impl Locator {
14    pub fn min() -> Self {
15        Self(smallvec![u64::MIN])
16    }
17
18    pub fn max() -> Self {
19        Self(smallvec![u64::MAX])
20    }
21
22    pub fn from_index(ix: usize, count: usize) -> Self {
23        let id = (1 + ix as u64) * (u64::MAX / (count as u64 + 2));
24        Self(smallvec![id])
25    }
26
27    pub fn assign(&mut self, other: &Self) {
28        self.0.resize(other.0.len(), 0);
29        self.0.copy_from_slice(&other.0);
30    }
31
32    pub fn between(lhs: &Self, rhs: &Self) -> Self {
33        let lhs = lhs.0.iter().copied().chain(iter::repeat(u64::MIN));
34        let rhs = rhs.0.iter().copied().chain(iter::repeat(u64::MAX));
35        let mut location = SmallVec::new();
36        for (lhs, rhs) in lhs.zip(rhs) {
37            let mid = lhs + ((rhs.saturating_sub(lhs)) >> 48);
38            location.push(mid);
39            if mid > lhs {
40                break;
41            }
42        }
43        Self(location)
44    }
45
46    pub fn len(&self) -> usize {
47        self.0.len()
48    }
49}
50
51impl Default for Locator {
52    fn default() -> Self {
53        Self::min()
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60    use rand::prelude::*;
61    use std::mem;
62
63    #[gpui::test(iterations = 100)]
64    fn test_locators(mut rng: StdRng) {
65        let mut lhs = Default::default();
66        let mut rhs = Default::default();
67        while lhs == rhs {
68            lhs = Locator(
69                (0..rng.gen_range(1..=5))
70                    .map(|_| rng.gen_range(0..=100))
71                    .collect(),
72            );
73            rhs = Locator(
74                (0..rng.gen_range(1..=5))
75                    .map(|_| rng.gen_range(0..=100))
76                    .collect(),
77            );
78        }
79
80        if lhs > rhs {
81            mem::swap(&mut lhs, &mut rhs);
82        }
83
84        let middle = Locator::between(&lhs, &rhs);
85        assert!(middle > lhs);
86        assert!(middle < rhs);
87        for ix in 0..middle.0.len() - 1 {
88            assert!(
89                middle.0[ix] == *lhs.0.get(ix).unwrap_or(&0)
90                    || middle.0[ix] == *rhs.0.get(ix).unwrap_or(&0)
91            );
92        }
93    }
94}