use core::{
cmp::Ordering,
fmt::Debug,
ops::{Deref, DerefMut},
};
use crate::token::Token;
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct Span {
index: usize,
length: usize,
}
impl Span {
#[inline]
#[must_use]
pub const unsafe fn new(index: usize, length: usize) -> Self {
Self { index, length }
}
#[inline]
#[must_use]
pub const unsafe fn new_single(index: usize) -> Self {
Self::new(index, 1)
}
#[inline]
#[must_use]
pub const unsafe fn new_empty(index: usize) -> Self {
Self::new(index, 0)
}
#[inline]
#[must_use]
pub const unsafe fn new_range(start_index: usize, end_index: usize) -> Self {
Self {
index: start_index,
length: end_index.unchecked_sub(start_index),
}
}
#[inline]
#[must_use]
pub const fn is_empty(&self) -> bool {
self.length == 0
}
#[inline]
#[must_use]
pub const fn index(&self) -> usize {
self.index
}
#[inline]
#[must_use]
pub const fn end_index(&self) -> usize {
unsafe { self.index.unchecked_add(self.length) }
}
#[inline]
#[must_use]
pub const fn len(&self) -> usize {
self.length
}
#[inline]
#[must_use]
pub const fn beginning(&self) -> Self {
unsafe { Self::new(self.index, 0) }
}
#[inline]
#[must_use]
pub const fn ending(&self) -> Self {
unsafe { Self::new(self.index.unchecked_add(self.length), 0) }
}
#[inline]
#[must_use]
pub fn range(&self, other: &Self) -> Self {
unsafe {
Self::new_range(
self.index.min(other.index),
self.end_index().max(other.end_index()),
)
}
}
#[inline]
#[must_use]
pub const fn up_to(&self, other: &Self) -> Self {
assert!(
other.index >= self.index,
"up_to called with out-of-order arguments"
);
unsafe { Self::new_range(self.index, other.index) }
}
#[inline]
pub fn wrap<T>(self, other: T) -> Spanned<T> {
other.spanned(self)
}
}
impl PartialOrd for Span {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Span {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.index.cmp(&other.index)
}
}
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[expect(clippy::exhaustive_structs)]
pub struct Spanned<T: ?Sized> {
pub span: Span,
pub data: T,
}
impl<T: ?Sized> Deref for Spanned<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<T: ?Sized> DerefMut for Spanned<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
impl<T> From<Token<T>> for Spanned<T> {
#[inline]
fn from(value: Token<T>) -> Self {
value.into_spanned()
}
}
pub trait Spannable {
fn spanned(self, span: Span) -> Spanned<Self>;
}
impl<T> Spannable for T {
#[inline]
fn spanned(self, span: Span) -> Spanned<Self> {
Spanned { span, data: self }
}
}