use std::fmt;
use thiserror::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Severity {
Error,
Warning,
}
impl fmt::Display for Severity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Self::Error => "error",
Self::Warning => "warning",
})
}
}
#[derive(Debug, Clone)]
pub struct Hint {
pub message: String,
pub file: Option<String>,
pub line: Option<usize>,
pub column: Option<usize>,
}
impl fmt::Display for Hint {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(file) = &self.file {
write!(f, "{file}")?;
if let Some(line) = self.line {
write!(f, ":{line}")?;
if let Some(col) = self.column {
write!(f, ":{col}")?;
}
}
write!(f, ": ")?;
}
f.write_str(&self.message)
}
}
#[derive(Debug, Clone)]
pub struct Diagnostic {
pub severity: Severity,
pub message: String,
pub file: Option<String>,
pub line: Option<usize>,
pub column: Option<usize>,
pub hints: Vec<Hint>,
}
impl fmt::Display for Diagnostic {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(file) = &self.file {
write!(f, "{file}")?;
if let Some(line) = self.line {
write!(f, ":{line}")?;
if let Some(col) = self.column {
write!(f, ":{col}")?;
}
}
write!(f, ": ")?;
}
write!(f, "{}: {}", self.severity, self.message)?;
for hint in &self.hints {
write!(f, "\n hint: {hint}")?;
}
Ok(())
}
}
#[derive(Debug, Error)]
pub enum PublishError {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Typst compilation failed:\n{}", .0.iter().map(ToString::to_string).collect::<Vec<_>>().join("\n"))]
Compilation(Vec<Diagnostic>),
#[cfg(feature = "pdf")]
#[error("PDF export failed:\n{}", .0.iter().map(ToString::to_string).collect::<Vec<_>>().join("\n"))]
Export(Vec<Diagnostic>),
#[cfg(feature = "html")]
#[error("HTML export failed:\n{}", .0.iter().map(ToString::to_string).collect::<Vec<_>>().join("\n"))]
HtmlExport(Vec<Diagnostic>),
#[error("Invalid JSON data: {0}")]
InvalidJson(#[from] serde_json::Error),
#[error("Invalid template: {0}")]
InvalidTemplate(String),
#[cfg(feature = "pdf")]
#[error("Invalid PDF standards: {0}")]
InvalidStandards(String),
#[cfg(feature = "image")]
#[error("Image processing failed: {0}")]
Image(String),
#[cfg(feature = "tokio")]
#[error("render exceeded the configured deadline")]
Timeout,
}
pub type Result<T> = std::result::Result<T, PublishError>;