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::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.saturating_sub(range.start) as u16,
77 source_id: context,
78 }
79 }
80
81 fn context(&self) -> Self::Context {
82 self.source_id
83 }
84
85 fn start(&self) -> Self::Offset {
86 self.start
87 }
88
89 fn end(&self) -> Self::Offset {
90 self.start + self.len as u32
91 }
92}
93
94#[cfg(test)]
95mod test {
96 use super::*;
97
98 #[test]
99 fn test_span_partial_cmp() {
100 let span1 = Span {
101 start: 10,
102 len: 20,
103 source_id: 1,
104 };
105 let span2 = Span {
106 start: 15,
107 len: 25,
108 source_id: 1,
109 };
110 let span3 = Span {
111 start: 5,
112 len: 15,
113 source_id: 2,
114 };
115
116 assert_eq!(span1.partial_cmp(&span2), Some(std::cmp::Ordering::Less));
118 assert_eq!(span2.partial_cmp(&span1), Some(std::cmp::Ordering::Greater));
119
120 assert_eq!(span1.partial_cmp(&span3), None);
122 assert_eq!(span3.partial_cmp(&span1), None);
123 }
124}