use std::fmt::Display;
use crate::MietteError;
pub trait Diagnostic: std::error::Error + Send + Sync + 'static {
fn code(&self) -> &(dyn Display + 'static);
fn severity(&self) -> Severity;
fn help(&self) -> Option<&[&str]> {
None
}
fn snippets(&self) -> Option<&[DiagnosticSnippet]> {
None
}
}
pub trait DiagnosticReporter: core::any::Any + Send + Sync {
fn debug(
&self,
diagnostic: &(dyn Diagnostic),
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result;
fn display(
&self,
diagnostic: &(dyn Diagnostic),
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
write!(f, "{}", diagnostic)?;
Ok(())
}
}
#[derive(Copy, Clone, Debug)]
pub enum Severity {
Error,
Warning,
Advice,
}
pub trait Source: std::fmt::Debug + Send + Sync + 'static {
fn read_span<'a>(&'a self, span: &SourceSpan)
-> Result<Box<dyn SpanContents<'a> + '_>, MietteError>;
}
pub trait SpanContents<'a> {
fn data(&self) -> &[u8];
fn line(&self) -> usize;
fn column(&self) -> usize;
}
#[derive(Clone, Debug)]
pub struct MietteSpanContents<'a> {
data: &'a [u8],
line: usize,
column: usize,
}
impl<'a> MietteSpanContents<'a> {
pub fn new(data: &'a [u8], line: usize, column: usize) -> MietteSpanContents<'a> {
MietteSpanContents { data, line, column }
}
}
impl<'a> SpanContents<'a> for MietteSpanContents<'a> {
fn data(&self) -> &[u8] {
self.data
}
fn line(&self) -> usize {
self.line
}
fn column(&self) -> usize {
self.column
}
}
#[derive(Debug)]
pub struct DiagnosticSnippet {
pub message: Option<String>,
pub source_name: String,
pub source: Box<dyn Source>,
pub context: SourceSpan,
pub highlights: Option<Vec<(String, SourceSpan)>>,
}
#[derive(Clone, Debug)]
pub struct SourceSpan {
pub start: SourceOffset,
pub end: SourceOffset,
}
impl SourceSpan {
pub fn new(start: SourceOffset, end: SourceOffset) -> Self {
assert!(
start.offset() <= end.offset(),
"Starting offset must come before the end offset."
);
Self { start, end }
}
pub fn len(&self) -> usize {
self.end.offset() - self.start.offset() + 1
}
pub fn is_empty(&self) -> bool {
self.start.offset() == self.end.offset()
}
}
pub type ByteOffset = usize;
#[derive(Clone, Copy, Debug)]
pub struct SourceOffset(ByteOffset);
impl SourceOffset {
pub fn offset(&self) -> ByteOffset {
self.0
}
}
impl From<ByteOffset> for SourceOffset {
fn from(bytes: ByteOffset) -> Self {
SourceOffset(bytes)
}
}