1use std::str::Utf8Error;
2use std::{borrow::Cow, io, result};
3
4use thiserror::Error;
5use url::ParseError;
6
7use crate::types::SqlType;
8
9#[derive(Debug, Error, Clone, Eq, PartialEq)]
10#[error("{} {} {}", name, code, message)]
11pub struct Exception {
12 pub name: String,
13 pub code: u32,
14 pub message: String,
15 #[cfg(test)]
16 pub(crate) trace: String,
17}
18
19#[derive(Debug, Error, Clone, Eq, PartialEq)]
21#[error("Server exception {}", _0[0])]
22pub struct ServerError(pub Box<[Exception]>);
23
24#[derive(Debug, Error, Clone, Eq, PartialEq)]
26pub enum UrlError {
27 #[error("Connection URL parameter `{}' requires feature `{}'", param, feature)]
28 FeatureRequired { feature: String, param: String },
29
30 #[error("Invalid or incomplete connection URL")]
31 Invalid,
32
33 #[error("Invalid value `{}' for connection URL parameter `{}'.", value, param)]
34 InvalidParamValue { param: String, value: String },
35
36 #[error("Invalid pool constraints: pool_min ({}) > pool_max ({}).", min, max)]
37 InvalidPoolConstraints { min: u16, max: u16 },
38
39 #[error("URL parse error: {}", _0)]
40 Parse(#[source] ParseError),
41
42 #[error("Unknown connection URL parameter `{}'.", param)]
43 UnknownParameter { param: String },
44
45 #[error("Unsupported connection URL scheme `{}'.", scheme)]
46 UnsupportedScheme { scheme: String },
47}
48
49#[derive(Debug, Error, Clone, PartialEq)]
51pub enum DriverError {
52 #[error("Connection to the server is closed.")]
53 ConnectionClosed,
54
55 #[error("Connection timeout.")]
56 ConnectionTimeout,
57
58 #[error("Packet {} out of order.", _0)]
59 PacketOutOfOrder(u64),
60
61 #[error("Pool was disconnected.")]
62 PoolDisconnected,
63
64 #[error("Unexpected packet.")]
65 UnexpectedPacket { code: u64, payload: Vec<u8> },
66
67 #[error("Unsupported data type.")]
68 UnsupportedType(SqlType),
69
70 #[error("Malformed packet data.")]
71 BrokenData,
72
73 #[error("Packet too large.")]
74 PacketTooLarge,
75
76 #[error("String too long.")]
77 StringTooLong,
78
79 #[error("Bad compressed packet header.")]
80 BadCompressedPacketHeader,
81
82 #[error("Bad packet hash.")]
83 BadHash,
84
85 #[error("Block row count {} exceed the limit.", _0)]
86 RowCountTooMany(u64),
87
88 #[error("Other operation in progress.")]
89 OperationInProgress,
90
91 #[error("Index out of range.")]
92 IndexOutOfRange,
93
94 #[error("Integrity error")]
95 IntegrityError,
96}
97
98#[derive(Debug, Error, Clone, PartialEq)]
100pub enum ConversionError {
101 #[error("Conversion unsupported")]
102 UnsupportedConversion,
103 #[error("fixed string length doesn't match column type. FixedString({})", _0)]
104 FixedStringLengthNotMatch(u32),
105 #[error("string value '{:?}' doesn't match enum value", _0)]
106 EnumMismatch(Vec<u8>),
107 #[error("Unknown column type '{}'", _0)]
108 UnknownColumnType(String),
109 #[error("Incorrect utf8 byte sequence")]
110 Utf8,
111}
112#[derive(Debug, Error)]
114pub enum Error {
115 #[error("Driver error: `{}'", _0)]
116 Driver(#[source] Box<DriverError>),
117
118 #[error("io error: `{}`", _0)]
119 Io(#[source] io::Error),
120
121 #[error("Server error: `{}'", _0)]
122 Server(#[source] ServerError),
123
124 #[error("URL error: `{}'", _0)]
125 Url(#[source] UrlError),
126
127 #[error("Deserialize error: `{}`", _0)]
128 Convertion(ConversionError),
129
130 #[error("Other error: `{}`", _0)]
131 Other(Cow<'static, str>),
132}
133
134impl Error {
135 pub fn is_timeout(&self) -> bool {
136 if let Error::Driver(berr) = self {
137 **berr == DriverError::ConnectionTimeout
138 } else {
139 false
140 }
141 }
142}
143
144pub type Result<T> = result::Result<T, Error>;
145
146impl From<io::Error> for Error {
147 fn from(err: io::Error) -> Self {
148 let kind = err.kind();
149 if err.get_ref().is_some() {
150 match err.into_inner().unwrap().downcast::<DriverError>() {
151 Ok(err) => Error::Driver(err),
152 _ => Error::Io(io::Error::from(kind)),
153 }
154 } else {
155 Error::Io(err)
156 }
157 }
158}
159
160impl From<Error> for io::Error {
161 fn from(err: Error) -> Self {
162 match err {
163 Error::Io(error) => error,
164 e => io::Error::new(io::ErrorKind::Other, e.to_string()),
165 }
166 }
167}
168
169impl From<ParseError> for UrlError {
170 fn from(err: ParseError) -> Self {
171 UrlError::Parse(err)
172 }
173}
174impl From<std::convert::Infallible> for Error {
176 fn from(_: std::convert::Infallible) -> Self {
177 Error::Other(Cow::Borrowed(""))
178 }
179}
180
181impl From<ParseError> for Error {
182 fn from(err: ParseError) -> Self {
183 Error::Url(err.into())
184 }
185}
186
187impl From<Utf8Error> for Error {
188 fn from(_err: Utf8Error) -> Self {
189 Error::Convertion(ConversionError::Utf8)
190 }
191}
192
193impl From<DriverError> for Error {
194 fn from(err: DriverError) -> Self {
195 Error::Driver(Box::new(err))
196 }
197}
198
199impl From<ServerError> for Error {
200 fn from(err: ServerError) -> Self {
201 Error::Server(err)
202 }
203}
204
205impl From<UrlError> for Error {
206 fn from(err: UrlError) -> Self {
207 Error::Url(err)
208 }
209}
210
211impl From<ConversionError> for Error {
212 fn from(err: ConversionError) -> Self {
213 Error::Convertion(err)
214 }
215}
216
217impl From<&'static str> for Error {
218 fn from(err: &'static str) -> Self {
219 Error::Other(Cow::Borrowed(err))
220 }
221}
222
223impl From<()> for Error {
224 fn from(_err: ()) -> Self {
225 Error::Other(Cow::Borrowed("unknown error"))
226 }
227}