use core::{
borrow::Borrow,
fmt,
hash::{Hash, Hasher},
ops::{Bound, Deref, DerefMut, Index, RangeBounds},
};
use serde::{Deserialize, Serialize};
use crate::range::Range;
use super::{ByteIndex, ByteOffset, SourceId};
pub trait Spanned {
fn span(&self) -> SourceSpan;
}
impl Spanned for SourceSpan {
#[inline(always)]
fn span(&self) -> SourceSpan {
*self
}
}
impl<T: ?Sized + Spanned> Spanned for &T {
fn span(&self) -> SourceSpan {
(**self).span()
}
}
impl<T: ?Sized + Spanned> Spanned for Box<T> {
fn span(&self) -> SourceSpan {
(**self).span()
}
}
impl<T: ?Sized + Spanned> Spanned for std::rc::Rc<T> {
fn span(&self) -> SourceSpan {
(**self).span()
}
}
impl<T: ?Sized + Spanned> Spanned for std::sync::Arc<T> {
fn span(&self) -> SourceSpan {
(**self).span()
}
}
pub struct Span<T> {
span: SourceSpan,
spanned: T,
}
impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for Span<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let spanned = T::deserialize(deserializer)?;
Ok(Self {
span: SourceSpan::UNKNOWN,
spanned,
})
}
}
impl<T: serde::Serialize> serde::Serialize for Span<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
T::serialize(&self.spanned, serializer)
}
}
impl<T> Spanned for Span<T> {
fn span(&self) -> SourceSpan {
self.span
}
}
impl<T: Copy> Copy for Span<T> {}
impl<T: Clone> Clone for Span<T> {
fn clone(&self) -> Self {
Self {
span: self.span,
spanned: self.spanned.clone(),
}
}
}
impl<T: Default> Default for Span<T> {
fn default() -> Self {
Self {
span: SourceSpan::UNKNOWN,
spanned: T::default(),
}
}
}
impl<T> Span<T> {
#[inline]
pub fn new(span: SourceSpan, spanned: T) -> Self {
Self { span, spanned }
}
#[inline]
pub fn at(source_id: SourceId, offset: usize, spanned: T) -> Self {
let offset = u32::try_from(offset).expect("invalid source offset: too large");
Self {
span: SourceSpan::at(source_id, offset),
spanned,
}
}
pub fn unknown(spanned: T) -> Self {
Self {
span: Default::default(),
spanned,
}
}
#[inline]
pub fn with_span(mut self, span: SourceSpan) -> Self {
self.span = span;
self
}
#[inline(always)]
pub const fn span(&self) -> SourceSpan {
self.span
}
#[inline(always)]
pub const fn inner(&self) -> &T {
&self.spanned
}
#[inline]
pub fn map<U, F>(self, mut f: F) -> Span<U>
where
F: FnMut(T) -> U,
{
Span {
span: self.span,
spanned: f(self.spanned),
}
}
pub fn as_deref<U>(&self) -> Span<&U>
where
U: ?Sized,
T: Deref<Target = U>,
{
Span {
span: self.span,
spanned: self.spanned.deref(),
}
}
pub fn as_ref(&self) -> Span<&T> {
Span {
span: self.span,
spanned: &self.spanned,
}
}
pub fn set_source_id(&mut self, id: SourceId) {
self.span.set_source_id(id);
}
#[inline]
pub fn shift(&mut self, count: ByteOffset) {
self.span.start += count;
self.span.end += count;
}
#[inline]
pub fn extend(&mut self, count: ByteOffset) {
self.span.end += count;
}
#[inline]
pub fn into_parts(self) -> (SourceSpan, T) {
(self.span, self.spanned)
}
#[inline]
pub fn into_inner(self) -> T {
self.spanned
}
}
impl<T> Borrow<T> for Span<T> {
fn borrow(&self) -> &T {
&self.spanned
}
}
impl<T: Borrow<str>> Borrow<str> for Span<T> {
fn borrow(&self) -> &str {
self.spanned.borrow()
}
}
impl<U, T: Borrow<[U]>> Borrow<[U]> for Span<T> {
fn borrow(&self) -> &[U] {
self.spanned.borrow()
}
}
impl<T> Deref for Span<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.spanned
}
}
impl<T> DerefMut for Span<T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.spanned
}
}
impl<T: ?Sized, U: AsRef<T>> AsRef<T> for Span<U> {
fn as_ref(&self) -> &T {
self.spanned.as_ref()
}
}
impl<T: ?Sized, U: AsMut<T>> AsMut<T> for Span<U> {
fn as_mut(&mut self) -> &mut T {
self.spanned.as_mut()
}
}
impl<T: fmt::Debug> fmt::Debug for Span<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.spanned, f)
}
}
impl<T: fmt::Display> fmt::Display for Span<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.spanned, f)
}
}
impl<T: Eq> Eq for Span<T> {}
impl<T: PartialEq> PartialEq for Span<T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.spanned.eq(&other.spanned)
}
}
impl<T: PartialEq> PartialEq<T> for Span<T> {
#[inline]
fn eq(&self, other: &T) -> bool {
self.spanned.eq(other)
}
}
impl<T: Ord> Ord for Span<T> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.spanned.cmp(&other.spanned)
}
}
impl<T: PartialOrd> PartialOrd for Span<T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.spanned.partial_cmp(&other.spanned)
}
}
impl<T: Hash> Hash for Span<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.spanned.hash(state);
}
}
#[derive(
Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
)]
pub struct SourceSpan {
#[serde(default, skip_serializing_if = "SourceId::is_unknown")]
source_id: SourceId,
start: ByteIndex,
end: ByteIndex,
}
#[derive(Debug, thiserror::Error)]
#[error("invalid byte index range: maximum supported byte index is 2^32")]
pub struct InvalidByteIndexRange;
impl SourceSpan {
pub const UNKNOWN: Self = Self {
source_id: SourceId::UNKNOWN,
start: ByteIndex::new(0),
end: ByteIndex::new(0),
};
pub fn new<B>(source_id: SourceId, range: Range<B>) -> Self
where
B: Into<ByteIndex>,
{
Self {
source_id,
start: range.start.into(),
end: range.end.into(),
}
}
pub fn at(source_id: SourceId, offset: impl Into<ByteIndex>) -> Self {
let offset = offset.into();
Self {
source_id,
start: offset,
end: offset,
}
}
pub fn try_from_range(
source_id: SourceId,
range: core::ops::Range<usize>,
) -> Result<Self, InvalidByteIndexRange> {
const MAX: usize = u32::MAX as usize;
if range.start > MAX || range.end > MAX {
return Err(InvalidByteIndexRange);
}
Ok(SourceSpan::from_range_unchecked(source_id, range))
}
#[inline]
pub fn from_range_unchecked(source_id: SourceId, range: core::ops::Range<usize>) -> Self {
SourceSpan {
source_id,
start: ByteIndex::from(range.start as u32),
end: ByteIndex::from(range.end as u32),
}
}
pub const fn is_unknown(&self) -> bool {
self.source_id.is_unknown()
}
#[inline(always)]
pub fn source_id(&self) -> SourceId {
self.source_id
}
pub fn set_source_id(&mut self, id: SourceId) {
self.source_id = id;
}
#[inline(always)]
pub fn start(&self) -> ByteIndex {
self.start
}
#[inline(always)]
pub fn end(&self) -> ByteIndex {
self.end
}
#[inline(always)]
pub fn len(&self) -> usize {
self.end.to_usize() - self.start.to_usize()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn into_range(self) -> Range<u32> {
Range::new(self.start.to_u32(), self.end.to_u32())
}
#[inline]
pub fn into_slice_index(self) -> Range<usize> {
Range::new(self.start.to_usize(), self.end.to_usize())
}
}
impl From<SourceSpan> for miette::SourceSpan {
fn from(span: SourceSpan) -> Self {
Self::new(
miette::SourceOffset::from(span.start().to_usize()),
span.len(),
)
}
}
impl From<SourceSpan> for Range<u32> {
#[inline(always)]
fn from(span: SourceSpan) -> Self {
span.into_range()
}
}
impl From<SourceSpan> for Range<usize> {
#[inline(always)]
fn from(span: SourceSpan) -> Self {
span.into_slice_index()
}
}
impl From<SourceSpan> for core::ops::Range<u32> {
fn from(value: SourceSpan) -> Self {
value.start.to_u32()..value.end.to_u32()
}
}
impl From<SourceSpan> for core::ops::Range<usize> {
fn from(value: SourceSpan) -> Self {
value.start.to_usize()..value.end.to_usize()
}
}
impl Index<SourceSpan> for [u8] {
type Output = [u8];
#[inline]
fn index(&self, index: SourceSpan) -> &Self::Output {
&self[index.start().to_usize()..index.end().to_usize()]
}
}
impl RangeBounds<ByteIndex> for SourceSpan {
#[inline(always)]
fn start_bound(&self) -> Bound<&ByteIndex> {
Bound::Included(&self.start)
}
#[inline(always)]
fn end_bound(&self) -> Bound<&ByteIndex> {
Bound::Excluded(&self.end)
}
}