#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct BytePos(pub u32);
impl BytePos {
pub const fn new(offset: u32) -> Self {
Self(offset)
}
pub const fn as_usize(self) -> usize {
self.0 as usize
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Span {
pub start: BytePos,
pub end: BytePos,
}
impl Span {
pub const fn new(start: BytePos, end: BytePos) -> Self {
Self { start, end }
}
pub fn from_offsets(start: usize, end: usize) -> Self {
Self {
start: BytePos(start as u32),
end: BytePos(end as u32),
}
}
pub const fn len(self) -> u32 {
self.end.0.saturating_sub(self.start.0)
}
pub fn merge(self, other: Span) -> Span {
Span {
start: self.start.min(other.start),
end: self.end.max(other.end),
}
}
pub fn line_col(self, source: &str) -> (usize, usize) {
let mut line = 1usize;
let mut col = 1usize;
for (i, ch) in source.char_indices() {
if i >= self.start.as_usize() {
break;
}
if ch == '\n' {
line += 1;
col = 1;
} else {
col += 1;
}
}
(line, col)
}
}