lutra_compiler/codespan/
span.rs1use std::fmt::{self, Debug, Formatter};
2
3#[derive(Clone, PartialEq, Eq, Copy)]
5pub struct Span {
6 pub start: u32,
8 pub len: u16,
10
11 pub source_id: u16,
14}
15
16impl Span {
17 pub fn set_end_of(&mut self, other: &Span) {
18 assert_eq!(self.source_id, other.source_id);
19 self.set_end(other.end());
20 }
21
22 pub fn set_end(&mut self, end: u32) {
23 self.len = end.saturating_sub(self.start) as u16;
24 }
25
26 pub fn end(&self) -> u32 {
27 self.start + self.len as u32
28 }
29
30 pub fn get_slice<'s>(&self, text: &'s str) -> &'s str {
31 &text[self.start as usize..self.end() as usize]
32 }
33
34 pub fn take_slice(&self, mut text: String) -> String {
35 text.truncate(self.end() as usize);
36 text.split_off(self.start as usize)
37 }
38
39 pub fn overlap(&self, other: &Self) -> bool {
40 self.start >= other.start && self.start < other.start + other.len as u32
41 }
42}
43
44impl From<Span> for std::ops::Range<usize> {
45 fn from(a: Span) -> Self {
46 a.start as usize..(a.start as usize + a.len as usize)
47 }
48}
49
50impl Debug for Span {
51 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
52 write!(f, "{}:{}-{}", self.source_id, self.start, self.end())
53 }
54}
55
56impl PartialOrd for Span {
57 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
58 match other.source_id.partial_cmp(&self.source_id) {
60 Some(std::cmp::Ordering::Equal) => self.start.partial_cmp(&other.start),
61 _ => None,
62 }
63 }
64}
65
66impl chumsky::Span for Span {
67 type Context = u16;
68
69 type Offset = u32;
70
71 fn new(context: Self::Context, range: std::ops::Range<Self::Offset>) -> Self {
72 Self {
73 start: range.start,
74 len: (range.end - range.start) as u16,
75 source_id: context,
76 }
77 }
78
79 fn context(&self) -> Self::Context {
80 self.source_id
81 }
82
83 fn start(&self) -> Self::Offset {
84 self.start
85 }
86
87 fn end(&self) -> Self::Offset {
88 self.start + self.len as u32
89 }
90}
91
92#[cfg(test)]
93mod test {
94 use super::*;
95
96 #[test]
97 fn test_span_partial_cmp() {
98 let span1 = Span {
99 start: 10,
100 len: 20,
101 source_id: 1,
102 };
103 let span2 = Span {
104 start: 15,
105 len: 25,
106 source_id: 1,
107 };
108 let span3 = Span {
109 start: 5,
110 len: 15,
111 source_id: 2,
112 };
113
114 assert_eq!(span1.partial_cmp(&span2), Some(std::cmp::Ordering::Less));
116 assert_eq!(span2.partial_cmp(&span1), Some(std::cmp::Ordering::Greater));
117
118 assert_eq!(span1.partial_cmp(&span3), None);
120 assert_eq!(span3.partial_cmp(&span1), None);
121 }
122}