1#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2pub struct Position {
3 pub line: u32,
4 pub column: u32,
5}
6
7impl Position {
8 pub const fn missing() -> Self {
9 Self {
10 line: u32::MAX,
11 column: u32::MAX,
12 }
13 }
14
15 pub const fn zero() -> Self {
16 Self { line: 0, column: 0 }
17 }
18
19 pub const fn new(line: u32, column: u32) -> Self {
20 Self { line, column }
21 }
22
23 pub const fn has_value(self) -> bool {
24 self.line != u32::MAX || self.column != u32::MAX
25 }
26
27 pub fn shift(&mut self, start: Position, old_end: Position, new_end: Position) {
28 if *self >= start {
30 if self.line > old_end.line {
31 self.line = self
32 .line
33 .wrapping_add(new_end.line.wrapping_sub(old_end.line));
34 } else {
35 self.line = new_end.line;
36 self.column = self
37 .column
38 .wrapping_add(new_end.column.wrapping_sub(old_end.column));
39 }
40 }
41 }
42}
43
44#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
45pub struct Location {
46 pub begin: Position,
47 pub end: Position,
48}
49
50impl Location {
51 pub const fn zero() -> Self {
52 Self {
53 begin: Position::zero(),
54 end: Position::zero(),
55 }
56 }
57
58 pub const fn new(begin: Position, end: Position) -> Self {
59 Self { begin, end }
60 }
61
62 pub const fn from_length(begin: Position, length: u32) -> Self {
63 Self {
64 begin,
65 end: Position {
66 line: begin.line,
67 column: begin.column + length,
68 },
69 }
70 }
71
72 pub const fn spanning(begin: Location, end: Location) -> Self {
73 Self {
74 begin: begin.begin,
75 end: end.end,
76 }
77 }
78
79 pub fn encloses(self, location: Location) -> bool {
80 self.begin <= location.begin && self.end >= location.end
81 }
82
83 pub fn overlaps(self, location: Location) -> bool {
84 (self.begin <= location.begin && self.end >= location.begin)
85 || (self.begin <= location.end && self.end >= location.end)
86 || (self.begin >= location.begin && self.end <= location.end)
87 }
88
89 pub fn contains(self, position: Position) -> bool {
90 self.begin <= position && position < self.end
91 }
92
93 pub fn contains_closed(self, position: Position) -> bool {
94 self.begin <= position && position <= self.end
95 }
96
97 pub fn extend(&mut self, other: Location) {
98 if other.begin < self.begin {
99 self.begin = other.begin;
100 }
101 if other.end > self.end {
102 self.end = other.end;
103 }
104 }
105
106 pub fn shift(&mut self, start: Position, old_end: Position, new_end: Position) {
107 self.begin.shift(start, old_end, new_end);
108 self.end.shift(start, old_end, new_end);
109 }
110}