#[derive(Clone, Copy, Debug)]
pub struct Location {
pub line: usize,
pub column: usize,
}
impl Location {
pub fn of_in(substr: &str, input: &str) -> Self {
let offset = (substr.as_ptr() as usize)
.checked_sub(input.as_ptr() as usize)
.expect("tried to find location of substring in unrelated string");
let mut bytes_prior = 0;
for (line_idx, line) in input.split('\n').enumerate() {
let bytes_so_far = bytes_prior + line.len() + 1;
if bytes_so_far > offset {
let line_offset = offset - bytes_prior;
let column = line[..line_offset].chars().count();
return Self {
line: line_idx + 1,
column: column + 1,
};
}
bytes_prior = bytes_so_far;
}
unreachable!()
}
#[cfg(feature = "experimental_parser")]
pub fn of_span_start(source: &str, span: Span) -> Self {
let offset = span.offset as usize;
let mut bytes_prior = 0;
for (line_idx, line) in source.split('\n').enumerate() {
let bytes_so_far = bytes_prior + line.len() + 1;
if bytes_so_far > offset {
let line_offset = offset - bytes_prior;
let column = line[..line_offset].chars().count();
return Self {
line: line_idx + 1,
column: column + 1,
};
}
bytes_prior = bytes_so_far;
}
unreachable!()
}
#[cfg(feature = "experimental_parser")]
pub fn of_span_end(source: &str, span: Span) -> Self {
let offset = span.offset as usize + span.len as usize;
let mut bytes_prior = 0;
for (line_idx, line) in source.split('\n').enumerate() {
let bytes_so_far = bytes_prior + line.len() + 1;
if bytes_so_far > offset {
let line_offset = offset - bytes_prior;
let column = line[..line_offset].chars().count();
return Self {
line: line_idx + 1,
column: column + 1,
};
}
bytes_prior = bytes_so_far;
}
unreachable!()
}
#[cfg(feature = "experimental_parser")]
pub fn range_of_span(source: &str, span: Span) -> Range<Self> {
let offset = span.offset as usize;
let end = offset + span.len as usize;
let mut bytes_prior = 0;
let mut iterator = source.split('\n').enumerate();
let start = loop {
let Some((line_idx, line)) = iterator.next() else {
panic!("tried to find location of span not belonging to string");
};
let bytes_so_far = bytes_prior + line.len() + 1;
if bytes_so_far > offset {
let line_offset = offset - bytes_prior;
let column = line[..line_offset].chars().count();
if bytes_so_far > end {
let line_offset = end - bytes_prior;
let end_column = line[..line_offset].chars().count();
return Self {
line: line_idx + 1,
column: column + 1,
}..Self {
line: line_idx + 1,
column: end_column + 1,
};
} else {
break Self {
line: line_idx + 1,
column: column + 1,
};
}
}
bytes_prior = bytes_so_far;
};
loop {
let Some((line_idx, line)) = iterator.next() else {
panic!("tried to find location of span not belonging to string");
};
let bytes_so_far = bytes_prior + line.len() + 1;
if bytes_so_far > end {
let line_offset = end - bytes_prior;
let column = line[..line_offset].chars().count();
return start..Self {
line: line_idx + 1,
column: column + 1,
};
}
}
}
}