1use super::{Buffer, Content};
2use anyhow::Result;
3use std::{cmp::Ordering, ops::Range};
4use sum_tree::Bias;
5
6#[derive(Clone, Eq, PartialEq, Debug, Hash)]
7pub struct Anchor {
8 pub offset: usize,
9 pub bias: Bias,
10 pub version: clock::Global,
11}
12
13impl Anchor {
14 pub fn min() -> Self {
15 Self {
16 offset: 0,
17 bias: Bias::Left,
18 version: Default::default(),
19 }
20 }
21
22 pub fn max() -> Self {
23 Self {
24 offset: usize::MAX,
25 bias: Bias::Right,
26 version: Default::default(),
27 }
28 }
29
30 pub fn cmp<'a>(&self, other: &Anchor, buffer: impl Into<Content<'a>>) -> Result<Ordering> {
31 let buffer = buffer.into();
32
33 if self == other {
34 return Ok(Ordering::Equal);
35 }
36
37 let offset_comparison = if self.version == other.version {
38 self.offset.cmp(&other.offset)
39 } else {
40 buffer
41 .full_offset_for_anchor(self)
42 .cmp(&buffer.full_offset_for_anchor(other))
43 };
44
45 Ok(offset_comparison.then_with(|| self.bias.cmp(&other.bias)))
46 }
47
48 pub fn bias_left(&self, buffer: &Buffer) -> Anchor {
49 if self.bias == Bias::Left {
50 self.clone()
51 } else {
52 buffer.anchor_before(self)
53 }
54 }
55
56 pub fn bias_right(&self, buffer: &Buffer) -> Anchor {
57 if self.bias == Bias::Right {
58 self.clone()
59 } else {
60 buffer.anchor_after(self)
61 }
62 }
63}
64
65pub trait AnchorRangeExt {
66 fn cmp<'a>(&self, b: &Range<Anchor>, buffer: impl Into<Content<'a>>) -> Result<Ordering>;
67}
68
69impl AnchorRangeExt for Range<Anchor> {
70 fn cmp<'a>(&self, other: &Range<Anchor>, buffer: impl Into<Content<'a>>) -> Result<Ordering> {
71 let buffer = buffer.into();
72 Ok(match self.start.cmp(&other.start, &buffer)? {
73 Ordering::Equal => other.end.cmp(&self.end, buffer)?,
74 ord @ _ => ord,
75 })
76 }
77}