1#[derive(Clone, PartialEq, Debug)]2pub struct CodeLocation {3 pub offset: usize,45 pub line: usize,6 pub column: usize,78 pub line_start_offset: usize,9 pub line_end_offset: usize,10}1112pub 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();1920 let mut offset_map = offsets21 .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();2728 let mut out = vec![29 CodeLocation {30 offset: 0,31 column: 0,32 line: 0,33 line_start_offset: 0,34 line_end_offset: 035 };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 file41 .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;6162 for idx in with_no_known_line_ending.drain(..) {63 out[idx].line_end_offset = pos;64 }65 this_line_offset = pos + 1;6667 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 }7677 out78}7980#[cfg(test)]81pub mod tests {82 use super::{offset_to_location, CodeLocation};8384 #[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: 67105 }106 ]107 )108 }109}