surrealdb_core/syn/error/
location.rsuse crate::syn::token::Span;
use std::ops::Range;
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
pub struct Location {
pub line: usize,
pub column: usize,
}
unsafe fn str_offset(a: &str, b: &str) -> usize {
b.as_ptr().offset_from(a.as_ptr()) as usize
}
impl Location {
fn range_of_source_end(source: &str) -> Range<Self> {
let (line, column) = source
.lines()
.enumerate()
.last()
.map(|(idx, line)| {
let idx = idx + 1;
let line_idx = line.chars().count().max(1);
(idx, line_idx)
})
.unwrap_or((1, 1));
Self {
line,
column,
}..Self {
line,
column: column + 1,
}
}
pub fn range_of_span(source: &str, span: Span) -> Range<Self> {
if source.len() <= span.offset as usize {
return Self::range_of_source_end(source);
}
let mut prev_line = "";
let mut lines = source.lines().enumerate().peekable();
let start_offset = span.offset as usize;
let start = loop {
let Some((line_idx, line)) = lines.peek().copied() else {
return Self::range_of_source_end(source);
};
let line_offset = unsafe { str_offset(source, line) };
if start_offset < line_offset {
let len = prev_line.chars().count();
break Self {
line: line_idx,
column: len + 1,
};
}
if (line_offset..(line_offset + line.len())).contains(&start_offset) {
let column_offset = start_offset - line_offset;
let column = line
.char_indices()
.enumerate()
.find(|(_, (char_idx, _))| *char_idx >= column_offset)
.map(|(l, _)| l)
.unwrap_or_else(|| {
line.chars().count()
});
break Self {
line: line_idx + 1,
column: column + 1,
};
}
lines.next();
prev_line = line;
};
let end_offset = span.offset as usize + span.len as usize;
let end = loop {
let Some((line_idx, line)) = lines.peek().copied() else {
break Self::range_of_source_end(source).end;
};
let line_offset = unsafe { str_offset(source, line) };
if end_offset < line_offset {
let len = prev_line.chars().count();
break Self {
line: line_idx,
column: len + 1,
};
}
if (line_offset..(line_offset + line.len())).contains(&end_offset) {
let column_offset = end_offset - line_offset;
let column = line
.char_indices()
.enumerate()
.find(|(_, (char_idx, _))| *char_idx >= column_offset)
.map(|(l, _)| l)
.unwrap_or_else(|| {
line.chars().count()
});
break Self {
line: line_idx + 1,
column: column + 1,
};
}
lines.next();
prev_line = line;
};
start..end
}
}