#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct Span {
pub start: usize,
pub len: usize,
pub file_id: Option<usize>,
pub line: usize,
pub column: usize,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct Spanned<T> {
pub inner: T,
pub span: Span,
}
impl Span {
pub fn new(start: usize, len: usize) -> Self {
Self {
start,
len,
file_id: None,
line: 1,
column: 1,
}
}
pub fn with_file(start: usize, len: usize, file_id: usize) -> Self {
Self {
start,
len,
file_id: Some(file_id),
line: 1,
column: 1,
}
}
pub fn end(&self) -> usize {
self.start + self.len
}
pub fn combine(self, other: Span) -> Span {
let start = self.start.min(other.start);
let end = self.end().max(other.end());
Span {
start,
len: end - start,
file_id: self.file_id.or(other.file_id),
line: self.line.min(other.line),
column: if self.line == other.line { self.column.min(other.column) } else { self.column },
}
}
pub fn contains(&self, pos: usize) -> bool {
pos >= self.start && pos < self.end()
}
pub fn overlaps(&self, other: Span) -> bool {
self.start < other.end() && other.start < self.end()
}
pub fn at(pos: usize) -> Self {
Self::new(pos, 0)
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn with_position(start: usize, len: usize, line: usize, column: usize) -> Self {
Self {
start,
len,
file_id: None,
line,
column,
}
}
}
impl<T> Spanned<T> {
pub fn new(inner: T, span: Span) -> Self {
Self { inner, span }
}
pub fn get_ref(&self) -> &T {
&self.inner
}
pub fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
pub fn into_inner(self) -> T {
self.inner
}
pub fn map<U, F>(self, f: F) -> Spanned<U>
where
F: FnOnce(T) -> U,
{
Spanned::new(f(self.inner), self.span)
}
pub fn try_map<U, E, F>(self, f: F) -> Result<Spanned<U>, E>
where
F: FnOnce(T) -> Result<U, E>,
{
match f(self.inner) {
Ok(value) => Ok(Spanned::new(value, self.span)),
Err(err) => Err(err),
}
}
}
impl<T> std::ops::Deref for Spanned<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T> std::ops::DerefMut for Spanned<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl Default for Span {
fn default() -> Self {
Self::new(0, 0)
}
}
pub fn spanned<T>(inner: T, span: Span) -> Spanned<T> {
Spanned::new(inner, span)
}
impl From<std::ops::Range<usize>> for Span {
fn from(range: std::ops::Range<usize>) -> Self {
Self::new(range.start, range.end - range.start)
}
}
pub fn range_to_span(range: std::ops::Range<usize>) -> Span {
range.into()
}