1use std::fmt;
4
5use thiserror::Error;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct SourceLocation {
13 pub file: String,
15 pub line: usize,
17 pub column: usize,
19}
20
21impl fmt::Display for SourceLocation {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 write!(f, "{}:{}:{}", self.file, self.line, self.column)
24 }
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum Severity {
30 Error,
32 Warning,
34}
35
36impl fmt::Display for Severity {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 match self {
39 Self::Error => f.write_str("error"),
40 Self::Warning => f.write_str("warning"),
41 }
42 }
43}
44
45#[derive(Debug, Clone, PartialEq, Eq)]
51#[non_exhaustive]
52pub struct Hint {
53 pub message: String,
55 pub location: Option<SourceLocation>,
57}
58
59impl fmt::Display for Hint {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 match &self.location {
62 Some(loc) => write!(f, "{loc}: {}", self.message),
63 None => f.write_str(&self.message),
64 }
65 }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq)]
70#[non_exhaustive]
71pub struct Diagnostic {
72 pub severity: Severity,
74 pub location: Option<SourceLocation>,
76 pub message: String,
78 pub hints: Vec<Hint>,
80 pub trace: Vec<SourceLocation>,
82}
83
84impl fmt::Display for Diagnostic {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 let severity = self.severity;
87 match &self.location {
88 Some(loc) => write!(f, "{loc}: {severity}: {}", self.message)?,
89 None => write!(f, "{severity}: {}", self.message)?,
90 }
91 for hint in &self.hints {
92 match &hint.location {
93 Some(loc) => write!(f, "\n hint at {loc}: {}", hint.message)?,
94 None => write!(f, "\n hint: {}", hint.message)?,
95 }
96 }
97 for site in &self.trace {
98 write!(f, "\n called from: {site}")?;
99 }
100 Ok(())
101 }
102}
103
104fn format_diagnostics(diagnostics: &[Diagnostic]) -> String {
106 diagnostics
107 .iter()
108 .map(|d| d.to_string())
109 .collect::<Vec<_>>()
110 .join("\n")
111}
112
113#[derive(Error, Debug)]
115pub enum Error {
116 #[error("entry file not found: {0}")]
118 EntryNotFound(&'static str),
119
120 #[error("entry file is not valid UTF-8")]
122 InvalidUtf8,
123
124 #[error("compilation failed:\n{}", format_diagnostics(.0))]
126 Compilation(Vec<Diagnostic>),
127
128 #[error("PDF generation failed: {0}")]
130 PdfGeneration(String),
131
132 #[error("PNG encoding failed: {0}")]
134 PngEncoding(String),
135
136 #[error("invalid file path: {0}")]
138 InvalidFilePath(String),
139
140 #[error("invalid page selection: {0}")]
142 InvalidPageSelection(String),
143
144 #[error("invalid PDF config: {0}")]
146 InvalidPdfConfig(String),
147
148 #[error("decompression failed")]
150 Decompression(#[from] std::io::Error),
151}
152
153pub type Result<T> = std::result::Result<T, Error>;