git.delta.rocks / jrsonnet / refs/commits / b89fdd32bd3a

difftreelog

source

crates/jrsonnet-ir/src/location.rs2.4 KiBsourcehistory
1#[allow(clippy::module_name_repetitions)]2#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]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<const S: usize>(file: &str, offsets: &[u32; S]) -> [CodeLocation; S] {28	if offsets.is_empty() {29		return [CodeLocation::default(); S];30	}31	let mut line = 1;32	let mut column = 0;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 = [CodeLocation::default(); S];44	let mut with_no_known_line_ending = vec![];45	let mut this_line_offset = 0;46	for (pos, ch) in file47		.chars()48		.enumerate()49		.chain(std::iter::once((file.len(), ' ')))50	{51		column += 1;52		match offset_map.last() {53			Some(x) if x.0 == pos as u32 => {54				let out_idx = x.1;55				with_no_known_line_ending.push(out_idx);56				out[out_idx].offset = pos;57				out[out_idx].line = line;58				out[out_idx].column = column;59				out[out_idx].line_start_offset = this_line_offset;60				offset_map.pop();61			}62			_ => {}63		}64		if ch == '\n' {65			line += 1;66			column = 0;6768			for idx in with_no_known_line_ending.drain(..) {69				out[idx].line_end_offset = pos;70			}71			this_line_offset = pos + 1;7273			if pos == max_offset as usize + 1 {74				break;75			}76		}77	}78	let file_end = file.chars().count();79	for idx in with_no_known_line_ending {80		out[idx].line_end_offset = file_end;81	}8283	out84}8586#[cfg(test)]87pub mod tests {88	use super::{CodeLocation, offset_to_location};8990	#[test]91	fn test() {92		assert_eq!(93			offset_to_location(94				"hello world\n_______________________________________________________",95				&[0, 14]96			),97			[98				CodeLocation {99					offset: 0,100					line: 1,101					column: 1,102					line_start_offset: 0,103					line_end_offset: 11,104				},105				CodeLocation {106					offset: 14,107					line: 2,108					column: 3,109					line_start_offset: 12,110					line_end_offset: 67111				}112			]113		)114	}115}