1use super::Buffer;
2use crate::{sum_tree, time};
3use anyhow::Result;
4use std::{cmp::Ordering, ops::Range};
5
6#[derive(Clone, Eq, PartialEq, Debug, Hash)]
7pub enum Anchor {
8 Start,
9 End,
10 Middle {
11 offset: usize,
12 bias: AnchorBias,
13 version: time::Global,
14 },
15}
16
17#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
18pub enum AnchorBias {
19 Left,
20 Right,
21}
22
23impl AnchorBias {
24 pub fn to_seek_bias(self) -> sum_tree::SeekBias {
25 match self {
26 AnchorBias::Left => sum_tree::SeekBias::Left,
27 AnchorBias::Right => sum_tree::SeekBias::Right,
28 }
29 }
30}
31
32impl PartialOrd for AnchorBias {
33 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
34 Some(self.cmp(other))
35 }
36}
37
38impl Ord for AnchorBias {
39 fn cmp(&self, other: &Self) -> Ordering {
40 use AnchorBias::*;
41
42 if self == other {
43 return Ordering::Equal;
44 }
45
46 match (self, other) {
47 (Left, _) => Ordering::Less,
48 (Right, _) => Ordering::Greater,
49 }
50 }
51}
52
53impl Anchor {
54 pub fn cmp(&self, other: &Anchor, buffer: &Buffer) -> Result<Ordering> {
55 if self == other {
56 return Ok(Ordering::Equal);
57 }
58
59 Ok(match (self, other) {
60 (Anchor::Start, _) | (_, Anchor::End) => Ordering::Less,
61 (Anchor::End, _) | (_, Anchor::Start) => Ordering::Greater,
62 (
63 Anchor::Middle {
64 bias: self_bias, ..
65 },
66 Anchor::Middle {
67 bias: other_bias, ..
68 },
69 ) => buffer
70 .fragment_ix_for_anchor(self)
71 .cmp(&buffer.fragment_ix_for_anchor(other))
72 .then_with(|| self_bias.cmp(&other_bias)),
73 })
74 }
75
76 pub fn bias_left(&self, buffer: &Buffer) -> Anchor {
77 match self {
78 Anchor::Start
79 | Anchor::Middle {
80 bias: AnchorBias::Left,
81 ..
82 } => self.clone(),
83 _ => buffer.anchor_before(self),
84 }
85 }
86
87 pub fn bias_right(&self, buffer: &Buffer) -> Anchor {
88 match self {
89 Anchor::End
90 | Anchor::Middle {
91 bias: AnchorBias::Right,
92 ..
93 } => self.clone(),
94 _ => buffer.anchor_after(self),
95 }
96 }
97}
98
99pub trait AnchorRangeExt {
100 fn cmp(&self, b: &Range<Anchor>, buffer: &Buffer) -> Result<Ordering>;
101}
102
103impl AnchorRangeExt for Range<Anchor> {
104 fn cmp(&self, other: &Range<Anchor>, buffer: &Buffer) -> Result<Ordering> {
105 Ok(match self.start.cmp(&other.start, buffer)? {
106 Ordering::Equal => other.end.cmp(&self.end, buffer)?,
107 ord @ _ => ord,
108 })
109 }
110}