use std::fmt::{self, Debug, Formatter};
#[derive(Clone, PartialEq, Eq, Copy)]
pub struct Span {
pub start: u32,
pub len: u16,
pub source_id: u16,
}
impl Span {
pub fn set_end_of(&mut self, other: &Span) {
assert_eq!(self.source_id, other.source_id);
self.set_end(other.end());
}
pub fn set_end(&mut self, end: u32) {
self.len = end.saturating_sub(self.start) as u16;
}
pub fn end(&self) -> u32 {
self.start + self.len as u32
}
pub fn get_slice<'s>(&self, text: &'s str) -> &'s str {
&text[self.start as usize..self.end() as usize]
}
pub fn take_slice(&self, mut text: String) -> String {
text.truncate(self.end() as usize);
text.split_off(self.start as usize)
}
pub fn overlap(&self, other: &Self) -> bool {
self.start >= other.start && self.start < other.start + other.len as u32
}
}
impl From<Span> for std::ops::Range<usize> {
fn from(a: Span) -> Self {
a.start as usize..(a.start as usize + a.len as usize)
}
}
impl Debug for Span {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}-{}", self.source_id, self.start, self.end())
}
}
impl PartialOrd for Span {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match other.source_id.partial_cmp(&self.source_id) {
Some(std::cmp::Ordering::Equal) => self.start.partial_cmp(&other.start),
_ => None,
}
}
}
impl chumsky::span::Span for Span {
type Context = u16;
type Offset = u32;
fn new(context: Self::Context, range: std::ops::Range<Self::Offset>) -> Self {
Self {
start: range.start,
len: range.end.saturating_sub(range.start) as u16,
source_id: context,
}
}
fn context(&self) -> Self::Context {
self.source_id
}
fn start(&self) -> Self::Offset {
self.start
}
fn end(&self) -> Self::Offset {
self.start + self.len as u32
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_span_partial_cmp() {
let span1 = Span {
start: 10,
len: 20,
source_id: 1,
};
let span2 = Span {
start: 15,
len: 25,
source_id: 1,
};
let span3 = Span {
start: 5,
len: 15,
source_id: 2,
};
assert_eq!(span1.partial_cmp(&span2), Some(std::cmp::Ordering::Less));
assert_eq!(span2.partial_cmp(&span1), Some(std::cmp::Ordering::Greater));
assert_eq!(span1.partial_cmp(&span3), None);
assert_eq!(span3.partial_cmp(&span1), None);
}
}