1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use distant_core::{RemoteProcessError, TransportError};
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum ExitCode {
Usage,
DataErr,
NoInput,
NoHost,
Unavailable,
Software,
OsErr,
IoError,
TempFail,
Protocol,
Custom(i32),
}
impl ExitCode {
pub fn to_i32(self) -> i32 {
match self {
Self::Usage => 64,
Self::DataErr => 65,
Self::NoInput => 66,
Self::NoHost => 68,
Self::Unavailable => 69,
Self::Software => 70,
Self::OsErr => 71,
Self::IoError => 74,
Self::TempFail => 75,
Self::Protocol => 76,
Self::Custom(x) => x,
}
}
}
impl From<ExitCode> for i32 {
fn from(code: ExitCode) -> Self {
code.to_i32()
}
}
pub trait ExitCodeError: std::error::Error {
fn to_exit_code(&self) -> ExitCode;
fn is_silent(&self) -> bool {
false
}
fn to_i32(&self) -> i32 {
self.to_exit_code().to_i32()
}
}
impl ExitCodeError for std::io::Error {
fn to_exit_code(&self) -> ExitCode {
use std::io::ErrorKind;
match self.kind() {
ErrorKind::ConnectionAborted
| ErrorKind::ConnectionRefused
| ErrorKind::ConnectionReset
| ErrorKind::NotConnected => ExitCode::Unavailable,
ErrorKind::InvalidData => ExitCode::DataErr,
ErrorKind::TimedOut => ExitCode::TempFail,
_ => ExitCode::IoError,
}
}
}
impl ExitCodeError for TransportError {
fn to_exit_code(&self) -> ExitCode {
match self {
TransportError::IoError(x) => x.to_exit_code(),
_ => ExitCode::Protocol,
}
}
}
impl ExitCodeError for RemoteProcessError {
fn is_silent(&self) -> bool {
true
}
fn to_exit_code(&self) -> ExitCode {
match self {
Self::ChannelDead => ExitCode::Unavailable,
Self::TransportError(x) => x.to_exit_code(),
Self::UnexpectedEof => ExitCode::IoError,
Self::WaitFailed(_) => ExitCode::Software,
}
}
}
impl<T: ExitCodeError + 'static> From<T> for Box<dyn ExitCodeError> {
fn from(x: T) -> Self {
Box::new(x)
}
}