Skip to main content

spar/
error.rs

1//! One error type. Every failure that a user could plausibly cause carries a
2//! sentence explaining what to do about it, because a failure whose reason is
3//! missing from the message costs more than the failure itself.
4
5use std::fmt;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct SparError {
9    message: String,
10}
11
12impl SparError {
13    pub fn new(message: impl Into<String>) -> Self {
14        Self {
15            message: message.into(),
16        }
17    }
18
19    pub fn message(&self) -> &str {
20        &self.message
21    }
22
23    /// The last line of a multi-line failure. Useful when a nested command's
24    /// own error is the interesting part and the preamble is not.
25    pub fn last_line(&self) -> &str {
26        self.message.lines().next_back().unwrap_or(&self.message)
27    }
28
29    /// The first line, for one-line status output.
30    pub fn first_line(&self) -> &str {
31        self.message.lines().next().unwrap_or(&self.message)
32    }
33}
34
35impl fmt::Display for SparError {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        f.write_str(&self.message)
38    }
39}
40
41impl std::error::Error for SparError {}
42
43impl From<std::io::Error> for SparError {
44    fn from(e: std::io::Error) -> Self {
45        SparError::new(e.to_string())
46    }
47}
48
49impl From<serde_json::Error> for SparError {
50    fn from(e: serde_json::Error) -> Self {
51        SparError::new(format!("invalid JSON: {e}"))
52    }
53}
54
55impl From<toml::de::Error> for SparError {
56    fn from(e: toml::de::Error) -> Self {
57        SparError::new(format!("invalid TOML: {e}"))
58    }
59}
60
61pub type Result<T> = std::result::Result<T, SparError>;
62
63/// Build a `SparError` with `format!` syntax.
64#[macro_export]
65macro_rules! spar_err {
66    ($($arg:tt)*) => { $crate::error::SparError::new(format!($($arg)*)) };
67}
68
69/// Return early with a `SparError`.
70#[macro_export]
71macro_rules! bail {
72    ($($arg:tt)*) => { return Err($crate::spar_err!($($arg)*)) };
73}