wave_compiler/diagnostics/
source_map.rs1use super::error::SourceLoc;
10
11pub struct SourceMap {
13 source: String,
14 line_starts: Vec<usize>,
15}
16
17impl SourceMap {
18 #[must_use]
20 pub fn new(source: String) -> Self {
21 let mut line_starts = vec![0];
22 for (i, ch) in source.char_indices() {
23 if ch == '\n' {
24 line_starts.push(i + 1);
25 }
26 }
27 Self {
28 source,
29 line_starts,
30 }
31 }
32
33 #[must_use]
35 pub fn offset_to_loc(&self, offset: usize) -> SourceLoc {
36 let line = self
37 .line_starts
38 .partition_point(|&start| start <= offset)
39 .saturating_sub(1);
40 let col = offset - self.line_starts[line];
41 SourceLoc {
42 #[allow(clippy::cast_possible_truncation)]
43 line: (line + 1) as u32,
44 #[allow(clippy::cast_possible_truncation)]
45 col: (col + 1) as u32,
46 }
47 }
48
49 #[must_use]
51 pub fn get_line(&self, line: u32) -> Option<&str> {
52 let idx = (line as usize).checked_sub(1)?;
53 let start = *self.line_starts.get(idx)?;
54 let end = self
55 .line_starts
56 .get(idx + 1)
57 .map_or(self.source.len(), |&s| s.saturating_sub(1));
58 Some(&self.source[start..end])
59 }
60
61 #[must_use]
63 pub fn line_count(&self) -> usize {
64 self.line_starts.len()
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn test_offset_to_loc() {
74 let src = "line1\nline2\nline3".to_string();
75 let map = SourceMap::new(src);
76 assert_eq!(map.offset_to_loc(0), SourceLoc { line: 1, col: 1 });
77 assert_eq!(map.offset_to_loc(6), SourceLoc { line: 2, col: 1 });
78 assert_eq!(map.offset_to_loc(8), SourceLoc { line: 2, col: 3 });
79 }
80
81 #[test]
82 fn test_get_line() {
83 let src = "first\nsecond\nthird".to_string();
84 let map = SourceMap::new(src);
85 assert_eq!(map.get_line(1), Some("first"));
86 assert_eq!(map.get_line(2), Some("second"));
87 assert_eq!(map.get_line(3), Some("third"));
88 assert_eq!(map.get_line(4), None);
89 }
90
91 #[test]
92 fn test_line_count() {
93 let src = "a\nb\nc\n".to_string();
94 let map = SourceMap::new(src);
95 assert_eq!(map.line_count(), 4);
96 }
97}