Skip to main content

mini_docs/
error.rs

1use std::fmt;
2
3/// Errors that can occur while building a Markdown → HTML site.
4///
5/// This error type is non-exhaustive and may gain new variants in future releases.
6///
7/// # Variants
8///
9/// - `Frontmatter`: the `---`-delimited frontmatter block is malformed.
10/// - `Markdown`: Markdown rendering failed.
11/// - `Template`: Tera template loading or rendering failed.
12/// - `Io`: an I/O error occurred (file read, write, or directory walk).
13/// - `Escape`: a resolved output path would have written outside `output_dir`.
14/// - `Extension`: a processor or analyzer failed; message is prefixed with extension name.
15#[derive(Debug)]
16#[non_exhaustive]
17pub enum DocError {
18    /// Malformed frontmatter block.
19    Frontmatter(String),
20    /// Markdown render failure.
21    Markdown(String),
22    /// Tera template load/render failure.
23    Template(tera::Error),
24    /// I/O error from the filesystem.
25    Io(std::io::Error),
26    /// Output path resolved outside `output_dir`.
27    Escape(String),
28    /// Extension (processor or analyzer) failure, prefixed with extension name.
29    Extension(String),
30}
31
32impl fmt::Display for DocError {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        match self {
35            DocError::Frontmatter(msg) => write!(f, "invalid frontmatter: {msg}"),
36            DocError::Markdown(msg) => write!(f, "markdown render error: {msg}"),
37            DocError::Template(e) => write!(f, "template error: {e}"),
38            DocError::Io(e) => write!(f, "io error: {e}"),
39            DocError::Escape(path) => write!(f, "output path escaped root: {path}"),
40            DocError::Extension(msg) => write!(f, "extension error: {msg}"),
41        }
42    }
43}
44
45impl std::error::Error for DocError {
46    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
47        match self {
48            DocError::Template(e) => Some(e),
49            DocError::Io(e) => Some(e),
50            _ => None,
51        }
52    }
53}
54
55impl DocError {
56    /// Returns a user-safe error message, never leaking filesystem or template internals.
57    pub fn user_message(&self) -> String {
58        match self {
59            DocError::Frontmatter(_) => "invalid frontmatter".to_string(),
60            DocError::Markdown(_) => "could not render markdown".to_string(),
61            DocError::Template(_) => "template error".to_string(),
62            DocError::Io(_) => "io error".to_string(),
63            DocError::Escape(_) => "output path escaped root".to_string(),
64            DocError::Extension(_) => "extension error".to_string(),
65        }
66    }
67}
68
69impl From<std::io::Error> for DocError {
70    fn from(e: std::io::Error) -> Self {
71        DocError::Io(e)
72    }
73}