mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-26 20:22:30 +00:00
125 lines
2.8 KiB
Rust
125 lines
2.8 KiB
Rust
use lazy_static::lazy_static;
|
|
use smallvec::{smallvec, SmallVec};
|
|
use std::iter;
|
|
|
|
lazy_static! {
|
|
static ref MIN: Locator = Locator::min();
|
|
static ref MAX: Locator = Locator::max();
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
pub struct Locator(SmallVec<[u64; 4]>);
|
|
|
|
impl Locator {
|
|
pub fn min() -> Self {
|
|
Self(smallvec![u64::MIN])
|
|
}
|
|
|
|
pub fn max() -> Self {
|
|
Self(smallvec![u64::MAX])
|
|
}
|
|
|
|
pub fn min_ref() -> &'static Self {
|
|
&*MIN
|
|
}
|
|
|
|
pub fn max_ref() -> &'static Self {
|
|
&*MAX
|
|
}
|
|
|
|
pub fn assign(&mut self, other: &Self) {
|
|
self.0.resize(other.0.len(), 0);
|
|
self.0.copy_from_slice(&other.0);
|
|
}
|
|
|
|
pub fn between(lhs: &Self, rhs: &Self) -> Self {
|
|
let lhs = lhs.0.iter().copied().chain(iter::repeat(u64::MIN));
|
|
let rhs = rhs.0.iter().copied().chain(iter::repeat(u64::MAX));
|
|
let mut location = SmallVec::new();
|
|
for (lhs, rhs) in lhs.zip(rhs) {
|
|
let mid = lhs + ((rhs.saturating_sub(lhs)) >> 48);
|
|
location.push(mid);
|
|
if mid > lhs {
|
|
break;
|
|
}
|
|
}
|
|
Self(location)
|
|
}
|
|
|
|
pub fn len(&self) -> usize {
|
|
self.0.len()
|
|
}
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
self.len() == 0
|
|
}
|
|
}
|
|
|
|
impl Default for Locator {
|
|
fn default() -> Self {
|
|
Self::min()
|
|
}
|
|
}
|
|
|
|
impl sum_tree::Item for Locator {
|
|
type Summary = Locator;
|
|
|
|
fn summary(&self) -> Self::Summary {
|
|
self.clone()
|
|
}
|
|
}
|
|
|
|
impl sum_tree::KeyedItem for Locator {
|
|
type Key = Locator;
|
|
|
|
fn key(&self) -> Self::Key {
|
|
self.clone()
|
|
}
|
|
}
|
|
|
|
impl sum_tree::Summary for Locator {
|
|
type Context = ();
|
|
|
|
fn add_summary(&mut self, summary: &Self, _: &()) {
|
|
self.assign(summary);
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use rand::prelude::*;
|
|
use std::mem;
|
|
|
|
#[gpui::test(iterations = 100)]
|
|
fn test_locators(mut rng: StdRng) {
|
|
let mut lhs = Default::default();
|
|
let mut rhs = Default::default();
|
|
while lhs == rhs {
|
|
lhs = Locator(
|
|
(0..rng.gen_range(1..=5))
|
|
.map(|_| rng.gen_range(0..=100))
|
|
.collect(),
|
|
);
|
|
rhs = Locator(
|
|
(0..rng.gen_range(1..=5))
|
|
.map(|_| rng.gen_range(0..=100))
|
|
.collect(),
|
|
);
|
|
}
|
|
|
|
if lhs > rhs {
|
|
mem::swap(&mut lhs, &mut rhs);
|
|
}
|
|
|
|
let middle = Locator::between(&lhs, &rhs);
|
|
assert!(middle > lhs);
|
|
assert!(middle < rhs);
|
|
for ix in 0..middle.0.len() - 1 {
|
|
assert!(
|
|
middle.0[ix] == *lhs.0.get(ix).unwrap_or(&0)
|
|
|| middle.0[ix] == *rhs.0.get(ix).unwrap_or(&0)
|
|
);
|
|
}
|
|
}
|
|
}
|