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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
use std::error;
use std::fmt;
use std::io;
use td_rp::RpError;
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum ErrorKind {
NoLeftSpaceError,
BufferOverMaxError,
TypeNotMatchError,
ParseError,
MissingError,
StringFormatError,
SqlError,
IoError,
RpError,
ExtensionError,
}
#[derive(Debug)]
enum ErrorRepr {
WithDescription(ErrorKind, &'static str),
WithDescriptionAndDetail(ErrorKind, &'static str, String),
ExtensionError(String, String),
IoError(io::Error),
RpError(RpError),
}
pub struct NetError {
repr: ErrorRepr,
}
pub type NetResult<T> = Result<T, NetError>;
impl PartialEq for NetError {
fn eq(&self, other: &NetError) -> bool {
match (&self.repr, &other.repr) {
(&ErrorRepr::WithDescription(kind_a, _), &ErrorRepr::WithDescription(kind_b, _)) => {
kind_a == kind_b
}
(&ErrorRepr::WithDescriptionAndDetail(kind_a, _, _),
&ErrorRepr::WithDescriptionAndDetail(kind_b, _, _)) => kind_a == kind_b,
(&ErrorRepr::ExtensionError(ref a, _), &ErrorRepr::ExtensionError(ref b, _)) => {
*a == *b
}
_ => false,
}
}
}
impl From<io::Error> for NetError {
fn from(err: io::Error) -> NetError {
NetError { repr: ErrorRepr::IoError(err) }
}
}
impl From<RpError> for NetError {
fn from(err: RpError) -> NetError {
NetError { repr: ErrorRepr::RpError(err) }
}
}
impl From<(ErrorKind, &'static str)> for NetError {
fn from((kind, desc): (ErrorKind, &'static str)) -> NetError {
NetError { repr: ErrorRepr::WithDescription(kind, desc) }
}
}
impl From<(ErrorKind, &'static str, String)> for NetError {
fn from((kind, desc, detail): (ErrorKind, &'static str, String)) -> NetError {
NetError { repr: ErrorRepr::WithDescriptionAndDetail(kind, desc, detail) }
}
}
impl error::Error for NetError {
fn description(&self) -> &str {
match self.repr {
ErrorRepr::WithDescription(_, desc) => desc,
ErrorRepr::WithDescriptionAndDetail(_, desc, _) => desc,
ErrorRepr::ExtensionError(_, _) => "extension error",
ErrorRepr::IoError(ref err) => err.description(),
ErrorRepr::RpError(ref err) => err.description(),
}
}
fn cause(&self) -> Option<&error::Error> {
match self.repr {
ErrorRepr::IoError(ref err) => Some(err as &error::Error),
_ => None,
}
}
}
impl fmt::Display for NetError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match self.repr {
ErrorRepr::WithDescription(_, desc) => desc.fmt(f),
ErrorRepr::WithDescriptionAndDetail(_, desc, ref detail) => {
try!(desc.fmt(f));
try!(f.write_str(": "));
detail.fmt(f)
}
ErrorRepr::ExtensionError(ref code, ref detail) => {
try!(code.fmt(f));
try!(f.write_str(": "));
detail.fmt(f)
}
ErrorRepr::IoError(ref err) => err.fmt(f),
ErrorRepr::RpError(ref err) => err.fmt(f),
}
}
}
impl fmt::Debug for NetError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
fmt::Display::fmt(self, f)
}
}
#[allow(dead_code)]
impl NetError {
pub fn kind(&self) -> ErrorKind {
match self.repr {
ErrorRepr::WithDescription(kind, _) => kind,
ErrorRepr::WithDescriptionAndDetail(kind, _, _) => kind,
ErrorRepr::ExtensionError(_, _) => ErrorKind::ExtensionError,
ErrorRepr::IoError(_) => ErrorKind::IoError,
ErrorRepr::RpError(_) => ErrorKind::RpError,
}
}
pub fn category(&self) -> &str {
match self.kind() {
ErrorKind::NoLeftSpaceError => "no left space error",
ErrorKind::BufferOverMaxError => "buffer over max error",
ErrorKind::TypeNotMatchError => "type not match error",
ErrorKind::ParseError => "parse error",
ErrorKind::MissingError => "missing error",
ErrorKind::StringFormatError => "string format error",
ErrorKind::SqlError => "sql error",
ErrorKind::IoError => "I/O error",
ErrorKind::ExtensionError => "extension error",
ErrorKind::RpError => "rust protocol error",
}
}
pub fn is_io_error(&self) -> bool {
match self.kind() {
ErrorKind::IoError => true,
_ => false,
}
}
pub fn extension_error_code(&self) -> Option<&str> {
match self.repr {
ErrorRepr::ExtensionError(ref code, _) => Some(&code),
_ => None,
}
}
pub fn extension_error_detail(&self) -> Option<&str> {
match self.repr {
ErrorRepr::ExtensionError(_, ref detail) => Some(&detail),
ErrorRepr::WithDescriptionAndDetail(_, _, ref detail) => Some(&detail),
_ => None,
}
}
}
pub fn make_extension_error(code: &str, detail: Option<&str>) -> NetError {
NetError {
repr: ErrorRepr::ExtensionError(code.to_string(),
match detail {
Some(x) => x.to_string(),
None => {
"Unknown extension error encountered".to_string()
}
}),
}
}