1#[allow(clippy::module_name_repetitions)]2#[derive(Clone, PartialEq, Eq, Debug)]3pub struct CodeLocation {4 pub offset: usize,56 pub line: usize,7 pub column: usize,89 pub line_start_offset: usize,10 pub line_end_offset: usize,11}1213#[allow(clippy::module_name_repetitions)]14pub fn location_to_offset(mut file: &str, mut line: usize, column: usize) -> Option<usize> {15 let mut offset = 0;16 while line > 1 {17 let pos = file.find('\n')?;18 offset += pos + 1;19 file = &file[pos + 1..];20 line -= 1;21 }22 offset += column - 1;23 Some(offset)24}2526#[allow(clippy::module_name_repetitions)]27pub fn offset_to_location(file: &str, offsets: &[u32]) -> Vec<CodeLocation> {28 if offsets.is_empty() {29 return vec![];30 }31 let mut line = 1;32 let mut column = 1;33 let max_offset = *offsets.iter().max().expect("offsets is not empty");3435 let mut offset_map = offsets36 .iter()37 .enumerate()38 .map(|(pos, offset)| (*offset, pos))39 .collect::<Vec<_>>();40 offset_map.sort_by_key(|v| v.0);41 offset_map.reverse();4243 let mut out = vec![44 CodeLocation {45 offset: 0,46 column: 0,47 line: 0,48 line_start_offset: 0,49 line_end_offset: 050 };51 offsets.len()52 ];53 let mut with_no_known_line_ending = vec![];54 let mut this_line_offset = 0;55 for (pos, ch) in file56 .chars()57 .enumerate()58 .chain(std::iter::once((file.len(), ' ')))59 {60 column += 1;61 match offset_map.last() {62 Some(x) if x.0 == pos as u32 => {63 let out_idx = x.1;64 with_no_known_line_ending.push(out_idx);65 out[out_idx].offset = pos;66 out[out_idx].line = line;67 out[out_idx].column = column;68 out[out_idx].line_start_offset = this_line_offset;69 offset_map.pop();70 }71 _ => {}72 }73 if ch == '\n' {74 line += 1;75 column = 1;7677 for idx in with_no_known_line_ending.drain(..) {78 out[idx].line_end_offset = pos;79 }80 this_line_offset = pos + 1;8182 if pos == max_offset as usize + 1 {83 break;84 }85 }86 }87 let file_end = file.chars().count();88 for idx in with_no_known_line_ending {89 out[idx].line_end_offset = file_end;90 }9192 out93}9495#[cfg(test)]96pub mod tests {97 use super::{offset_to_location, CodeLocation};9899 #[test]100 fn test() {101 assert_eq!(102 offset_to_location(103 "hello world\n_______________________________________________________",104 &[0, 14]105 ),106 vec![107 CodeLocation {108 offset: 0,109 line: 1,110 column: 2,111 line_start_offset: 0,112 line_end_offset: 11,113 },114 CodeLocation {115 offset: 14,116 line: 2,117 column: 4,118 line_start_offset: 12,119 line_end_offset: 67120 }121 ]122 )123 }124}