use std::fmt::{self, Debug, Display};
use std::ops::Range;
#[cfg(feature = "filename")]
use std::path::PathBuf;
#[cfg(feature = "filename")]
use std::sync::Arc;
use crate::libyaml::error::Mark;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Span {
pub start: Marker,
pub end: Marker,
#[cfg(feature = "filename")]
pub filename: Option<Arc<PathBuf>>,
}
impl Span {
pub fn new(start: Marker, end: Marker) -> Self {
Span {
start,
end,
#[cfg(feature = "filename")]
filename: None,
}
}
pub fn is_valid(&self) -> bool {
self.start.index <= self.end.index
&& self.start.line > 0
&& self.start.column > 0
&& self.end.line > 0
&& self.end.column > 0
}
pub const fn zero() -> Self {
Span {
start: Marker::zero(),
end: Marker::zero(),
#[cfg(feature = "filename")]
filename: None,
}
}
}
#[cfg(feature = "filename")]
impl Span {
pub fn new_with_filename(
start: impl Into<Marker>,
end: impl Into<Marker>,
filename: impl Into<Arc<PathBuf>>,
) -> Self {
Span {
start: start.into(),
end: end.into(),
filename: Some(filename.into()),
}
}
pub fn with_filename(self, filename: impl Into<Arc<PathBuf>>) -> Self {
Span {
filename: Some(filename.into()),
..self
}
}
pub fn get_filename(&self) -> Option<&std::path::Path> {
self.filename.as_deref().map(|f| f.as_ref())
}
pub(crate) fn maybe_capture_filename(self) -> Self {
if let Some(filename) = crate::spanned::get_filename() {
Self {
filename: Some(filename),
..self
}
} else {
self
}
}
}
impl Default for Span {
fn default() -> Self {
Span::zero()
}
}
impl Debug for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}..{:?}", self.start, self.end)
}
}
impl Display for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}..{}", self.start, self.end)
}
}
impl From<(Marker, Marker)> for Span {
fn from((start, end): (Marker, Marker)) -> Self {
Span::new(start, end)
}
}
impl From<Range<Option<Marker>>> for Span {
fn from(range: Range<Option<Marker>>) -> Self {
let start = range.start.unwrap_or_default();
let end = range.end.unwrap_or_default();
Span::new(start, end)
}
}
impl From<Marker> for Span {
fn from(marker: Marker) -> Self {
Span::new(marker, marker)
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Marker {
pub index: usize,
pub line: usize,
pub column: usize,
}
impl Marker {
pub fn new(index: usize, line: usize, column: usize) -> Self {
Marker {
index,
line,
column,
}
}
pub const fn start() -> Self {
Marker {
index: 0,
line: 1,
column: 1,
}
}
pub const fn zero() -> Self {
Marker {
index: 0,
line: 0,
column: 0,
}
}
pub fn line(&self) -> usize {
self.line
}
pub fn column(&self) -> usize {
self.column
}
pub fn index(&self) -> usize {
self.index
}
}
impl Default for Marker {
fn default() -> Self {
Marker::zero()
}
}
impl From<Mark> for Marker {
fn from(mark: Mark) -> Self {
Marker {
index: mark.index() as usize,
line: mark.line() as usize + 1,
column: mark.column() as usize + 1,
}
}
}
impl Debug for Marker {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}[{}]", self.line, self.column, self.index)
}
}
impl Display for Marker {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "line {} column {}", self.line, self.column)
}
}