clickhouse_rs_async/errors/
mod.rs1use std::{borrow::Cow, io, result, str::Utf8Error, string::FromUtf8Error};
2
3use thiserror::Error;
4#[cfg(feature = "tokio_io")]
5use tokio::time::error::Elapsed;
6use url::ParseError;
7
8#[cfg(feature = "tls-native-tls")]
9use native_tls::Error as TlsError;
10#[cfg(feature = "tls-rustls")]
11use rustls::Error as TlsError;
12
13pub mod codes;
15
16pub type Result<T> = result::Result<T, Error>;
18
19#[derive(Debug, Error)]
21pub enum Error {
22 #[error("Driver error: `{}`", _0)]
23 Driver(#[source] DriverError),
24
25 #[error("Input/output error: `{}`", _0)]
26 Io(#[source] io::Error),
27
28 #[error("Connections error: `{}`", _0)]
29 Connection(#[source] ConnectionError),
30
31 #[error("Other error: `{}`", _0)]
32 Other(Cow<'static, str>),
33
34 #[error("Server error: `{}`", _0)]
35 Server(#[source] ServerError),
36
37 #[error("URL error: `{}`", _0)]
38 Url(#[source] UrlError),
39
40 #[error("From SQL error: `{}`", _0)]
41 FromSql(#[source] FromSqlError),
42}
43
44#[derive(Debug, Error, Clone)]
46#[error("ERROR {} ({}): {}", name, code, message)]
47pub struct ServerError {
48 pub code: u32,
49 pub name: String,
50 pub message: String,
51 pub stack_trace: String,
52}
53
54#[derive(Debug, Error)]
56pub enum ConnectionError {
57 #[error("TLS connection requires hostname to be provided")]
58 TlsHostNotProvided,
59
60 #[error("Input/output error: `{}`", _0)]
61 IoError(#[source] io::Error),
62
63 #[cfg(feature = "_tls")]
64 #[error("TLS connection error: `{}`", _0)]
65 TlsError(#[source] TlsError),
66
67 #[error("Connection broken")]
68 Broken,
69}
70
71#[derive(Debug, Error)]
73pub enum UrlError {
74 #[error("Invalid or incomplete connection URL")]
75 Invalid,
76
77 #[error("Invalid value `{}' for connection URL parameter `{}'", value, param)]
78 InvalidParamValue { param: String, value: String },
79
80 #[error("URL parse error: {}", _0)]
81 Parse(#[source] ParseError),
82
83 #[error("Unknown connection URL parameter `{}'", param)]
84 UnknownParameter { param: String },
85
86 #[error("Unsupported connection URL scheme `{}'", scheme)]
87 UnsupportedScheme { scheme: String },
88}
89
90#[derive(Debug, Error)]
92pub enum DriverError {
93 #[error("Varint overflows a 64-bit integer.")]
94 Overflow,
95
96 #[error("Unknown packet 0x{:x}.", packet)]
97 UnknownPacket { packet: u64 },
98
99 #[error("Unexpected packet.")]
100 UnexpectedPacket,
101
102 #[error("Timeout error.")]
103 Timeout,
104
105 #[error("Invalid utf-8 sequence.")]
106 Utf8Error(Utf8Error),
107
108 #[error("Deserialize error: `{}`", _0)]
109 Deserialize(Cow<'static, str>),
110}
111
112#[derive(Debug, Error)]
114pub enum FromSqlError {
115 #[error("SqlType::{} cannot be cast to {}.", src, dst)]
116 InvalidType {
117 src: Cow<'static, str>,
118 dst: Cow<'static, str>,
119 },
120
121 #[error("Out of range.")]
122 OutOfRange,
123
124 #[error("Unsupported operation.")]
125 UnsupportedOperation,
126}
127
128impl Error {
129 pub(crate) fn is_would_block(&self) -> bool {
130 if let Error::Io(ref e) = self {
131 if e.kind() == io::ErrorKind::WouldBlock {
132 return true;
133 }
134 }
135 false
136 }
137}
138
139impl From<ConnectionError> for Error {
140 fn from(error: ConnectionError) -> Self {
141 Error::Connection(error)
142 }
143}
144
145#[cfg(feature = "_tls")]
146impl From<TlsError> for ConnectionError {
147 fn from(error: TlsError) -> Self {
148 ConnectionError::TlsError(error)
149 }
150}
151
152impl From<DriverError> for Error {
153 fn from(err: DriverError) -> Self {
154 Error::Driver(err)
155 }
156}
157
158impl From<io::Error> for Error {
159 fn from(err: io::Error) -> Self {
160 Error::Io(err)
161 }
162}
163
164impl From<ServerError> for Error {
165 fn from(err: ServerError) -> Self {
166 Error::Server(err)
167 }
168}
169
170impl From<UrlError> for Error {
171 fn from(err: UrlError) -> Self {
172 Error::Url(err)
173 }
174}
175
176impl From<String> for Error {
177 fn from(err: String) -> Self {
178 Error::Other(Cow::from(err))
179 }
180}
181
182impl From<&str> for Error {
183 fn from(err: &str) -> Self {
184 Error::Other(err.to_string().into())
185 }
186}
187
188impl From<FromUtf8Error> for Error {
189 fn from(err: FromUtf8Error) -> Self {
190 Error::Other(err.to_string().into())
191 }
192}
193
194#[cfg(feature = "tokio_io")]
195impl From<Elapsed> for Error {
196 fn from(_err: Elapsed) -> Self {
197 Error::Driver(DriverError::Timeout)
198 }
199}
200
201impl From<ParseError> for Error {
202 fn from(err: ParseError) -> Self {
203 Error::Url(UrlError::Parse(err))
204 }
205}
206
207impl From<Error> for io::Error {
208 fn from(err: Error) -> Self {
209 match err {
210 Error::Io(error) => error,
211 e => io::Error::new(io::ErrorKind::Other, e.to_string()),
212 }
213 }
214}
215
216impl From<Utf8Error> for Error {
217 fn from(err: Utf8Error) -> Self {
218 Error::Driver(DriverError::Utf8Error(err))
219 }
220}
221
222#[cfg(test)]
223mod tests {
224 #[test]
225 fn to_std_error_without_recursion() {
226 let src_err: super::Error = From::from("Somth went wrong.");
227 let dst_err: Box<dyn std::error::Error> = src_err.into();
228 assert_eq!(dst_err.to_string(), "Other error: `Somth went wrong.`");
229 }
230
231 #[test]
232 fn to_io_error_without_recursion() {
233 let src_err: super::Error = From::from("Somth went wrong.");
234 let dst_err: std::io::Error = src_err.into();
235 assert_eq!(dst_err.to_string(), "Other error: `Somth went wrong.`");
236 }
237}