jrsonnet_evaluator/trace/
location.rs1#[derive(Clone, PartialEq, Debug)]
2pub struct CodeLocation {
3 pub offset: usize,
4
5 pub line: usize,
6 pub column: usize,
7
8 pub line_start_offset: usize,
9 pub line_end_offset: usize,
10}
11
12pub fn offset_to_location(file: &str, offsets: &[usize]) -> Vec<CodeLocation> {
13 if offsets.is_empty() {
14 return vec![];
15 }
16 let mut line = 1;
17 let mut column = 1;
18 let max_offset = *offsets.iter().max().unwrap();
19
20 let mut offset_map = offsets
21 .iter()
22 .enumerate()
23 .map(|(pos, offset)| (*offset, pos))
24 .collect::<Vec<_>>();
25 offset_map.sort_by_key(|v| v.0);
26 offset_map.reverse();
27
28 let mut out = vec![
29 CodeLocation {
30 offset: 0,
31 column: 0,
32 line: 0,
33 line_start_offset: 0,
34 line_end_offset: 0
35 };
36 offsets.len()
37 ];
38 let mut with_no_known_line_ending = vec![];
39 let mut this_line_offset = 0;
40 for (pos, ch) in file
41 .chars()
42 .enumerate()
43 .chain(std::iter::once((file.len(), ' ')))
44 {
45 column += 1;
46 match offset_map.last() {
47 Some(x) if x.0 == pos => {
48 let out_idx = x.1;
49 with_no_known_line_ending.push(out_idx);
50 out[out_idx].offset = pos;
51 out[out_idx].line = line;
52 out[out_idx].column = column;
53 out[out_idx].line_start_offset = this_line_offset;
54 offset_map.pop();
55 }
56 _ => {}
57 }
58 if ch == '\n' {
59 line += 1;
60 column = 1;
61
62 for idx in with_no_known_line_ending.drain(..) {
63 out[idx].line_end_offset = pos;
64 }
65 this_line_offset = pos + 1;
66
67 if pos == max_offset + 1 {
68 break;
69 }
70 }
71 }
72 let file_end = file.chars().count();
73 for idx in with_no_known_line_ending {
74 out[idx].line_end_offset = file_end;
75 }
76
77 out
78}
79
80#[cfg(test)]
81pub mod tests {
82 use super::{offset_to_location, CodeLocation};
83
84 #[test]
85 fn test() {
86 assert_eq!(
87 offset_to_location(
88 "hello world\n_______________________________________________________",
89 &[0, 14]
90 ),
91 vec![
92 CodeLocation {
93 offset: 0,
94 line: 1,
95 column: 2,
96 line_start_offset: 0,
97 line_end_offset: 11,
98 },
99 CodeLocation {
100 offset: 14,
101 line: 2,
102 column: 4,
103 line_start_offset: 12,
104 line_end_offset: 67
105 }
106 ]
107 )
108 }
109}