You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
2.6 KiB
Rust
122 lines
2.6 KiB
Rust
use std::ops::{Deref, DerefMut};
|
|
#[cfg(feature = "miette")]
|
|
use miette::SourceSpan;
|
|
|
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
|
|
pub struct Span<V, O = usize> {
|
|
pub start: O,
|
|
pub end: O,
|
|
pub value: V,
|
|
}
|
|
|
|
impl<V, O> Span<V, O> {
|
|
pub fn with_value<N>(self, value: N) -> Span<N, O> {
|
|
Span {
|
|
start: self.start,
|
|
end: self.end,
|
|
value,
|
|
}
|
|
}
|
|
|
|
pub fn empty(self) -> Span<(), O> {
|
|
self.with_value(())
|
|
}
|
|
}
|
|
|
|
impl<V: ToString, O> Span<V, O> {
|
|
pub fn into_string(self) -> Span<String, O> {
|
|
Span {
|
|
start: self.start,
|
|
end: self.end,
|
|
value: self.value.to_string()
|
|
}
|
|
}
|
|
}
|
|
|
|
pub trait SpanOffset {
|
|
fn absolute_offset(&self) -> usize;
|
|
}
|
|
|
|
impl SpanOffset for usize {
|
|
fn absolute_offset(&self) -> usize {
|
|
*self
|
|
}
|
|
}
|
|
|
|
impl<V, O> Span<V, O> {
|
|
#[inline]
|
|
pub fn new(start: O, end: O, value: V) -> Self {
|
|
Span {
|
|
start,
|
|
end,
|
|
value,
|
|
}
|
|
}
|
|
|
|
pub fn unwrap(self) -> V {
|
|
self.value
|
|
}
|
|
}
|
|
|
|
impl<V, O> Deref for Span<V, O> {
|
|
type Target = V;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.value
|
|
}
|
|
}
|
|
|
|
impl<V, O> DerefMut for Span<V, O> {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.value
|
|
}
|
|
}
|
|
|
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
|
|
pub struct LineOffset {
|
|
pub line: usize,
|
|
pub line_offset: usize,
|
|
pub absolute_offset: usize,
|
|
}
|
|
|
|
impl LineOffset {
|
|
pub fn new(line: usize, line_offset: usize, absolute_offset: usize) -> LineOffset {
|
|
LineOffset {
|
|
line,
|
|
line_offset,
|
|
absolute_offset,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpanOffset for LineOffset {
|
|
fn absolute_offset(&self) -> usize {
|
|
self.absolute_offset
|
|
}
|
|
}
|
|
|
|
pub type LineSpan<V> = Span<V, LineOffset>;
|
|
|
|
#[cfg(feature = "miette")]
|
|
impl<V, T: SpanOffset> Into<SourceSpan> for &Span<V, T> {
|
|
fn into(self) -> SourceSpan {
|
|
(self.start.absolute_offset(), self.end.absolute_offset() - self.start.absolute_offset()).into()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::lexer::{LineTracker, Tracker};
|
|
use crate::span::{LineOffset, Span, SpanOffset};
|
|
|
|
#[test]
|
|
pub fn simple_test() {
|
|
let mut line_tracker = LineTracker::default();
|
|
|
|
line_tracker.start(0);
|
|
line_tracker.process_newline(2);
|
|
assert_eq!(Span::new(LineOffset::new(0, 0, 0), LineOffset::new(1, 1, 4), ()), line_tracker.end(4, ()));
|
|
assert_eq!(1, LineOffset::new(0, 0, 1).absolute_offset());
|
|
assert_eq!(1, 1usize.absolute_offset());
|
|
}
|
|
} |