language_reporting/
simple.rs

1#[derive(Debug, Clone)]
2pub struct SimpleFile {
3    name: String,
4    contents: String,
5}
6
7#[derive(Debug, Clone, Default)]
8pub struct SimpleReportingFiles {
9    files: Vec<SimpleFile>,
10}
11
12impl SimpleReportingFiles {
13    pub fn add(&mut self, name: impl Into<String>, value: impl Into<String>) -> usize {
14        self.files.push(SimpleFile {
15            name: name.into(),
16            contents: value.into(),
17        });
18
19        self.files.len() - 1
20    }
21}
22
23impl crate::ReportingFiles for SimpleReportingFiles {
24    type Span = SimpleSpan;
25    type FileId = usize;
26
27    fn file_id(&self, span: SimpleSpan) -> usize {
28        span.file_id
29    }
30
31    fn file_name(&self, id: usize) -> crate::FileName {
32        crate::FileName::Verbatim(self.files[id].name.clone())
33    }
34
35    fn byte_span(&self, _file: usize, _from_index: usize, _to_index: usize) -> Option<Self::Span> {
36        unimplemented!()
37    }
38
39    fn byte_index(&self, file: usize, line: usize, column: usize) -> Option<usize> {
40        let source = &self.files[file].contents;
41        let mut seen_lines = 0;
42        let mut seen_bytes = 0;
43
44        for (pos, _) in source.match_indices('\n') {
45            if seen_lines == line {
46                return Some(seen_bytes + column);
47            } else {
48                seen_lines += 1;
49                seen_bytes = pos + 1;
50            }
51        }
52
53        None
54    }
55
56    fn location(&self, file: usize, index: usize) -> Option<crate::Location> {
57        let source = &self.files[file].contents;
58        let mut seen_lines = 0;
59        let mut seen_bytes = 0;
60
61        for (pos, _) in source.match_indices('\n') {
62            if pos > index {
63                return Some(crate::Location::new(seen_lines, index - seen_bytes));
64            } else {
65                seen_lines += 1;
66                seen_bytes = pos;
67            }
68        }
69
70        None
71    }
72
73    fn line_span(&self, file: usize, line: usize) -> Option<Self::Span> {
74        let source = &self.files[file].contents;
75        let mut seen_lines = 0;
76        let mut seen_bytes = 0;
77
78        for (pos, _) in source.match_indices('\n') {
79            if seen_lines == line {
80                return Some(SimpleSpan::new(file, seen_bytes, pos));
81            } else {
82                seen_lines += 1;
83                seen_bytes = pos + 1;
84            }
85        }
86
87        None
88    }
89
90    fn source(&self, span: SimpleSpan) -> Option<String> {
91        let source = &self.files[span.file_id].contents;
92
93        Some(source[span.start..span.end].to_string())
94    }
95}
96
97#[derive(Debug, Copy, Clone)]
98pub struct SimpleSpan {
99    file_id: usize,
100    start: usize,
101    end: usize,
102}
103
104impl SimpleSpan {
105    pub fn new(file_id: usize, start: usize, end: usize) -> SimpleSpan {
106        assert!(
107            end >= start,
108            "SimpleSpan {} must be bigger than {}",
109            end,
110            start
111        );
112
113        SimpleSpan {
114            file_id,
115            start,
116            end,
117        }
118    }
119}
120
121impl crate::ReportingSpan for SimpleSpan {
122    fn with_start(&self, start: usize) -> Self {
123        SimpleSpan::new(self.file_id, start, self.end)
124    }
125
126    fn with_end(&self, end: usize) -> Self {
127        SimpleSpan::new(self.file_id, self.start, end)
128    }
129
130    fn start(&self) -> usize {
131        self.start
132    }
133
134    fn end(&self) -> usize {
135        self.end
136    }
137}