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