1use std::{io, process};
4
5use clap::error::ErrorKind as ClapErrorKind;
6
7use crate::error::Error as WordTallyError;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[repr(u8)]
12pub enum ExitCode {
13 Success = 0,
15 Failure = 1,
17 UsageError = 64,
19 DataFormat = 65,
21 InputNotFound = 66,
23 InternalError = 70,
25 OutputFailed = 73,
27 IoError = 74,
29 PermissionDenied = 77,
31}
32
33impl From<&io::Error> for ExitCode {
34 fn from(err: &io::Error) -> Self {
35 match err.kind() {
36 io::ErrorKind::NotFound => Self::InputNotFound,
37 io::ErrorKind::PermissionDenied => Self::PermissionDenied,
38 io::ErrorKind::AlreadyExists => Self::OutputFailed,
39 _ => Self::IoError,
40 }
41 }
42}
43
44impl From<&clap::Error> for ExitCode {
45 fn from(err: &clap::Error) -> Self {
46 match err.kind() {
47 ClapErrorKind::DisplayHelp | ClapErrorKind::DisplayVersion => Self::Success,
49 _ => Self::UsageError,
51 }
52 }
53}
54
55impl From<&WordTallyError> for ExitCode {
56 fn from(err: &WordTallyError) -> Self {
57 match err {
58 WordTallyError::Usage(_)
59 | WordTallyError::StdinNotMappable
60 | WordTallyError::NotMappable { .. }
61 | WordTallyError::PathInvalid
62 | WordTallyError::BytesRequired
63 | WordTallyError::Config(_) => Self::UsageError,
64 WordTallyError::Utf8 { .. }
65 | WordTallyError::Pattern { .. }
66 | WordTallyError::Json(_)
67 | WordTallyError::Csv(_)
68 | WordTallyError::ChunkOverflow { .. }
69 | WordTallyError::BatchOverflow { .. } => Self::DataFormat,
70 WordTallyError::MutexPoisoned => Self::InternalError,
71 WordTallyError::Io { source, .. } => Self::from(source),
72 }
73 }
74}
75
76impl From<&anyhow::Error> for ExitCode {
77 fn from(err: &anyhow::Error) -> Self {
78 err.downcast_ref::<io::Error>()
79 .map(Self::from)
80 .or_else(|| err.downcast_ref::<clap::Error>().map(Self::from))
81 .or_else(|| err.downcast_ref::<WordTallyError>().map(Self::from))
82 .unwrap_or(Self::Failure)
83 }
84}
85
86impl From<ExitCode> for process::ExitCode {
87 fn from(code: ExitCode) -> Self {
88 Self::from(code as u8)
89 }
90}