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

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());
}
}