Skip to main content

shifty_parse/
diagnostics.rs

1//! Parse/lowering diagnostics. Unsupported constructs are reported here rather
2//! than silently dropped (gap-analysis principle: never a silent wrong answer).
3
4use serde::{Deserialize, Serialize};
5use std::fmt;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8pub enum DiagLevel {
9    Warning,
10    Unsupported,
11    Error,
12}
13
14#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
15pub struct Diagnostic {
16    pub level: DiagLevel,
17    pub message: String,
18    /// The shape/term the diagnostic concerns, rendered for display.
19    pub subject: Option<String>,
20}
21
22impl Diagnostic {
23    pub fn new(level: DiagLevel, message: impl Into<String>, subject: Option<String>) -> Self {
24        Self {
25            level,
26            message: message.into(),
27            subject,
28        }
29    }
30}
31
32impl fmt::Display for Diagnostic {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        let tag = match self.level {
35            DiagLevel::Warning => "warning",
36            DiagLevel::Unsupported => "unsupported",
37            DiagLevel::Error => "error",
38        };
39        match &self.subject {
40            Some(s) => write!(f, "[{tag}] {} ({s})", self.message),
41            None => write!(f, "[{tag}] {}", self.message),
42        }
43    }
44}
45
46/// Fatal parse error (e.g. malformed Turtle).
47#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct ParseError(pub String);
49
50impl fmt::Display for ParseError {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        write!(f, "{}", self.0)
53    }
54}
55
56impl std::error::Error for ParseError {}