Skip to main content

tzcompile/
error.rs

1//! Error and diagnostic plumbing.
2//!
3//! Two layers, deliberately:
4//!
5//! * [`Diagnostic`] — a *located, coded* message about the source
6//!   (the user's tzdata). These are what a tzdata author wants to read.
7//! * [`Error`] — the crate's `Result` error. It either wraps a diagnostic (most parse and
8//!   compile failures carry one) or describes an environmental failure (I/O, an unusable
9//!   configuration, a failed oracle invocation).
10
11use std::path::{Path, PathBuf};
12
13use crate::diagnostics::Diagnostic;
14
15/// Crate-wide result type.
16pub type Result<T> = std::result::Result<T, Error>;
17
18/// The crate's top-level error.
19#[derive(Debug, thiserror::Error)]
20pub enum Error {
21    /// A located, coded problem with the source or the requested compilation.
22    #[error("{0}")]
23    Diagnostic(Box<Diagnostic>),
24
25    /// An I/O failure against a specific path.
26    #[error("{path}: {source}")]
27    Io {
28        path: PathBuf,
29        #[source]
30        source: std::io::Error,
31    },
32
33    /// A configuration problem (e.g. missing `--out`).
34    #[error("{0}")]
35    Config(String),
36
37    /// A free-form internal error that is not tied to a source location.
38    #[error("{0}")]
39    Message(String),
40}
41
42impl Error {
43    /// Wrap a path-tagged I/O error.
44    pub fn io(path: impl Into<PathBuf>, source: std::io::Error) -> Self {
45        Error::Io {
46            path: path.into(),
47            source,
48        }
49    }
50
51    /// Build a configuration error.
52    pub fn config(msg: impl Into<String>) -> Self {
53        Error::Config(msg.into())
54    }
55
56    /// Build a free-form error.
57    pub fn message(msg: impl Into<String>) -> Self {
58        Error::Message(msg.into())
59    }
60
61    /// Borrow the wrapped diagnostic, if this is one.
62    pub fn diagnostic(&self) -> Option<&Diagnostic> {
63        match self {
64            Error::Diagnostic(d) => Some(d),
65            _ => None,
66        }
67    }
68}
69
70impl From<Diagnostic> for Error {
71    fn from(d: Diagnostic) -> Self {
72        Error::Diagnostic(Box::new(d))
73    }
74}
75
76/// Helper for I/O against a borrowed path.
77pub(crate) fn io_at<T>(path: &Path, r: std::io::Result<T>) -> Result<T> {
78    r.map_err(|e| Error::io(path, e))
79}