1use std::fmt;
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
15#[repr(i32)]
16pub enum ExitCode {
17 Success = 0,
19 GenericError = 1,
21 Usage = 2,
23 Config = 3,
25 Build = 4,
27 TestFailure = 5,
29 Network = 6,
31 User = 7,
33 Interrupted = 8,
35}
36
37impl ExitCode {
38 pub const fn to_i32(self) -> i32 {
40 self as i32
41 }
42
43 pub const fn name(self) -> &'static str {
45 match self {
46 Self::Success => "Success",
47 Self::GenericError => "GenericError",
48 Self::Usage => "Usage",
49 Self::Config => "Config",
50 Self::Build => "Build",
51 Self::TestFailure => "TestFailure",
52 Self::Network => "Network",
53 Self::User => "User",
54 Self::Interrupted => "Interrupted",
55 }
56 }
57}
58
59impl fmt::Display for ExitCode {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 write!(f, "{} ({})", self.name(), self.to_i32())
62 }
63}
64
65impl From<ExitCode> for i32 {
66 fn from(code: ExitCode) -> Self {
67 code.to_i32()
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn numeric_codes_match_spec() {
77 assert_eq!(ExitCode::Success.to_i32(), 0);
78 assert_eq!(ExitCode::GenericError.to_i32(), 1);
79 assert_eq!(ExitCode::Usage.to_i32(), 2);
80 assert_eq!(ExitCode::Config.to_i32(), 3);
81 assert_eq!(ExitCode::Build.to_i32(), 4);
82 assert_eq!(ExitCode::TestFailure.to_i32(), 5);
83 assert_eq!(ExitCode::Network.to_i32(), 6);
84 assert_eq!(ExitCode::User.to_i32(), 7);
85 assert_eq!(ExitCode::Interrupted.to_i32(), 8);
86 }
87}