use std::{fmt::Display, sync::Arc};
#[derive(Clone, Default, Debug)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(
any(test, feature = "serde"),
derive(PartialEq, Eq, serde::Serialize, serde::Deserialize)
)]
pub struct SourcePosition {
pub index: usize,
pub line: usize,
pub column: usize,
}
impl Display for SourcePosition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{},{}", self.line, self.column))
}
}
impl SourcePosition {
#[must_use]
pub const fn offset(&self, offset: &SourcePositionOffset) -> Self {
Self {
index: self.index + offset.index,
line: self.line + offset.line,
column: if offset.line == 0 {
self.column + offset.column
} else {
offset.column + 1
},
}
}
}
#[cfg(feature = "diagnostics")]
impl From<&SourcePosition> for miette::SourceOffset {
#[allow(clippy::cast_sign_loss)]
fn from(position: &SourcePosition) -> Self {
position.index.into()
}
}
#[derive(Clone, Default, Debug)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(
any(test, feature = "serde"),
derive(PartialEq, Eq, serde::Serialize, serde::Deserialize)
)]
pub struct SourcePositionOffset {
pub index: usize,
pub line: usize,
pub column: usize,
}
#[derive(Clone, Default, Debug)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(
any(test, feature = "serde"),
derive(PartialEq, Eq, serde::Serialize, serde::Deserialize)
)]
pub struct SourceSpan {
pub start: Arc<SourcePosition>,
pub end: Arc<SourcePosition>,
}
impl SourceSpan {
pub fn length(&self) -> usize {
self.end.index - self.start.index
}
pub(crate) fn within(start: &Self, end: &Self) -> Self {
Self {
start: start.start.clone(),
end: end.end.clone(),
}
}
}