diff options
author | Teddy Wing | 2021-03-14 04:50:29 +0100 |
---|---|---|
committer | Teddy Wing | 2021-03-14 04:55:11 +0100 |
commit | 05a556f7cc92b7710f7b4f509be9376a0296b21e (patch) | |
tree | c420442efd19bedaefae4baef8e2a6e9a4aeb2ec | |
parent | 0fa5b304ed57517ba04b7a42ff30258e456972f8 (diff) | |
download | mutt-ottolangy-05a556f7cc92b7710f7b4f509be9376a0296b21e.tar.bz2 |
Add additional sysexits error codes for other errors
Give types to the errors in `run()` and exit with appropriate error
codes.
Split out an additional error type so we can wrap errors from the
non-main functions.
Remove 'anyhow', replacing it with 'thiserror' now that we're using
error types.
-rw-r--r-- | Cargo.lock | 7 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/main.rs | 54 |
3 files changed, 37 insertions, 25 deletions
@@ -7,12 +7,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" [[package]] -name = "anyhow" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" - -[[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -95,7 +89,6 @@ dependencies = [ name = "ottolangy" version = "0.0.1" dependencies = [ - "anyhow", "exitcode", "mailparse", "thiserror", @@ -4,7 +4,6 @@ version = "0.0.1" edition = "2018" [dependencies] -anyhow = "1.0.38" exitcode = "1.1.2" mailparse = "0.13.2" thiserror = "1.0.24" diff --git a/src/main.rs b/src/main.rs index a50b42d..a763037 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. -use anyhow::{anyhow, Context, Error}; use exitcode; use mailparse; use thiserror; @@ -42,7 +41,7 @@ const ATTRIBUTION_EN: &'static str = #[derive(thiserror::Error, Debug)] -enum OttolangyError { +enum WrapError { #[error("unable to parse email body: {0}")] ParseMail(#[from] mailparse::MailParseError), @@ -56,22 +55,43 @@ enum OttolangyError { Io(#[from] std::io::Error), } +#[derive(thiserror::Error, Debug)] +enum OttolangyError { + #[error("failed to read from stdin: {0}")] + ReadStdin(#[from] std::io::Error), + + #[error("unable to detect language")] + DetectLanguage, + + #[error("failed to write attribution config file")] + WriteConfig(WrapError), + + #[error(transparent)] + Wrapped(WrapError), +} + -// TODO: exit codes fn main() { match run() { Ok(_) => (), Err(e) => { eprintln!("{}: error: {}", PROGRAM_NAME, e); - match e.downcast_ref::<OttolangyError>() { - Some(OttolangyError::ParseMail(_)) => + match e { + OttolangyError::Wrapped(WrapError::ParseMail(_)) => process::exit(exitcode::DATAERR), - Some(OttolangyError::ParseMailUnknown) => + OttolangyError::Wrapped(WrapError::ParseMailUnknown) => process::exit(exitcode::DATAERR), - Some(OttolangyError::Xdg(_)) => process::exit(exitcode::IOERR), - Some(OttolangyError::Io(_)) => process::exit(exitcode::IOERR), - None => process::exit(exitcode::UNAVAILABLE), + OttolangyError::Wrapped(WrapError::Xdg(_)) => + process::exit(exitcode::IOERR), + OttolangyError::Wrapped(WrapError::Io(_)) => + process::exit(exitcode::IOERR), + OttolangyError::ReadStdin(_) => + process::exit(exitcode::NOINPUT), + OttolangyError::DetectLanguage => + process::exit(exitcode::SOFTWARE), + OttolangyError::WriteConfig(_) => + process::exit(exitcode::IOERR), } }, } @@ -79,18 +99,18 @@ fn main() { /// Get an email from standard input and write a Mutt attribution config based /// on the language. -fn run() -> Result<(), Error> { +fn run() -> Result<(), OttolangyError> { let mut email_input: Vec<u8> = Vec::new(); let mut stdin = io::stdin(); stdin.read_to_end(&mut email_input) - .context("failed to read from stdin")?; + .map_err(|e| OttolangyError::ReadStdin(e))?; let body = get_email_body(&email_input) - .context("failed to parse email body")?; + .map_err(|e| OttolangyError::Wrapped(e))?; let lang_info = whatlang::detect(&body) - .ok_or(anyhow!("unable to detect language"))?; + .ok_or(OttolangyError::DetectLanguage)?; let attribution_config = if lang_info.lang() == Lang::Fra { ATTRIBUTION_FR @@ -99,7 +119,7 @@ fn run() -> Result<(), Error> { }; write_attribution(&attribution_config) - .context("failed to write attribution config file")?; + .map_err(|e| OttolangyError::WriteConfig(e))?; Ok(()) } @@ -108,7 +128,7 @@ fn run() -> Result<(), Error> { /// /// Given an email as input, parses it and extracts the body. For multipart /// emails, the body is extracted from the text part. -fn get_email_body(email: &[u8]) -> Result<String, OttolangyError> { +fn get_email_body(email: &[u8]) -> Result<String, WrapError> { let email = mailparse::parse_mail(&email)?; if email.subparts.is_empty() { @@ -127,13 +147,13 @@ fn get_email_body(email: &[u8]) -> Result<String, OttolangyError> { } } - Err(OttolangyError::ParseMailUnknown) + Err(WrapError::ParseMailUnknown) } /// Write the attribution config to a file. /// /// Store the file in the XDG data directory. -fn write_attribution(config: &str) -> Result<(), OttolangyError> { +fn write_attribution(config: &str) -> Result<(), WrapError> { let xdg_dirs = xdg::BaseDirectories::with_prefix(PROGRAM_NAME)?; let muttrc_path = xdg_dirs.place_data_file(MUTTRC_FILENAME)?; |