use std::ops::Range;
use std::fmt::Debug;
pub type Pos = usize;
#[derive(Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Span {
pub lo: Pos,
pub hi: Pos,
}
impl From<Range<Pos>> for Span {
#[inline]
fn from(range: Range<Pos>) -> Self {
Self {
lo: range.start,
hi: range.end,
}
}
}
impl From<(Pos, Pos)> for Span {
#[inline]
fn from((lo, hi): (Pos, Pos)) -> Self {
Self { lo, hi }
}
}
impl Span {
#[inline]
pub fn new(lo: Pos, hi: Pos) -> Self {
Self { lo, hi }
}
pub fn get<'s>(&self, input: &'s str) -> &'s str {
if self.hi <= self.lo {
return "";
}
let hi = self.hi.min(input.len());
&input[self.lo..hi]
}
}
impl Debug for Span {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.hi <= self.lo {
write!(f, "{}", self.lo)
} else {
write!(f, "{}..{}", self.lo, self.hi)
}
}
}
pub trait ToSpan {
fn span(&self) -> Span;
}
pub use teleparse_macros::ToSpan;
impl ToSpan for Span {
#[inline]
fn span(&self) -> Span {
*self
}
}
macro_rules! derive_to_span_tuple {
($last:tt, $($n:ident),*) => {
impl<$($n: ToSpan),*> ToSpan for ($($n,)*) {
#[inline]
fn span(&self) -> Span {
(self.0.span().lo, self.$last.span().hi).into()
}
}
};
}
derive_to_span_tuple!(1, A, B);
derive_to_span_tuple!(2, A, B, C);
derive_to_span_tuple!(3, A, B, C, D);
derive_to_span_tuple!(4, A, B, C, D, E);