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}