irc/
error.rs

1//! Errors for `irc` crate using `failure`.
2
3use std::io::Error as IoError;
4use std::sync::mpsc::RecvError;
5
6use thiserror::Error;
7use tokio::sync::mpsc::error::{SendError, TrySendError};
8#[cfg(feature = "tls-rust")]
9use tokio_rustls::rustls::pki_types::InvalidDnsNameError;
10
11use crate::proto::error::{MessageParseError, ProtocolError};
12
13/// A specialized `Result` type for the `irc` crate.
14pub type Result<T, E = Error> = std::result::Result<T, E>;
15
16/// The main crate-wide error type.
17#[derive(Debug, Error)]
18pub enum Error {
19    /// An internal I/O error.
20    #[error("an io error occurred")]
21    Io(
22        #[source]
23        #[from]
24        IoError,
25    ),
26
27    /// An internal proxy error.
28    #[cfg(feature = "proxy")]
29    #[error("a proxy error occurred")]
30    Proxy(#[from] tokio_socks::Error),
31
32    /// An internal TLS error.
33    #[cfg(all(feature = "tls-native", not(feature = "tls-rust")))]
34    #[error("a TLS error occurred: {0}")]
35    Tls(
36        #[source]
37        #[from]
38        native_tls::Error,
39    ),
40
41    /// An internal TLS error.
42    #[cfg(feature = "tls-rust")]
43    #[error("a TLS error occurred")]
44    Tls(
45        #[source]
46        #[from]
47        tokio_rustls::rustls::Error,
48    ),
49
50    /// An invalid DNS name was specified.
51    #[cfg(feature = "tls-rust")]
52    #[error("invalid DNS name")]
53    InvalidDnsNameError(
54        #[source]
55        #[from]
56        InvalidDnsNameError,
57    ),
58
59    /// An internal synchronous channel closed.
60    #[error("a sync channel closed")]
61    SyncChannelClosed(
62        #[source]
63        #[from]
64        RecvError,
65    ),
66
67    /// An internal asynchronous channel closed.
68    #[error("an async channel closed")]
69    AsyncChannelClosed,
70
71    /// An internal oneshot channel closed.
72    #[error("a oneshot channel closed")]
73    OneShotCanceled,
74
75    /// Error for invalid configurations.
76    #[error("invalid config: {}", path)]
77    InvalidConfig {
78        /// The path to the configuration, or "<none>" if none specified.
79        path: String,
80        /// The detailed configuration error.
81        #[source]
82        cause: ConfigError,
83    },
84
85    /// Error for invalid messages.
86    #[error("invalid message: {}", string)]
87    InvalidMessage {
88        /// The string that failed to parse.
89        string: String,
90        /// The detailed message parsing error.
91        #[source]
92        cause: MessageParseError,
93    },
94
95    /// Mutex for a logged transport was poisoned making the log inaccessible.
96    #[error("mutex for a logged transport was poisoned")]
97    PoisonedLog,
98
99    /// Ping timed out due to no response.
100    #[error("connection reset: no ping response")]
101    PingTimeout,
102
103    /// Failed to lookup an unknown codec.
104    #[error("unknown codec: {}", codec)]
105    UnknownCodec {
106        /// The attempted codec.
107        codec: String,
108    },
109
110    /// Failed to encode or decode something with the given codec.
111    #[error("codec {} failed: {}", codec, data)]
112    CodecFailed {
113        /// The canonical codec name.
114        codec: &'static str,
115        /// The data that failed to encode or decode.
116        data: String,
117    },
118
119    /// All specified nicknames were in use or unusable.
120    #[error("none of the specified nicknames were usable")]
121    NoUsableNick,
122
123    /// Stream has already been configured.
124    #[error("stream has already been configured")]
125    StreamAlreadyConfigured,
126}
127
128/// Errors that occur with configurations.
129#[derive(Debug, Error)]
130pub enum ConfigError {
131    /// Failed to parse as TOML.
132    #[cfg(feature = "toml_config")]
133    #[error("invalid toml")]
134    InvalidToml(#[source] TomlError),
135
136    /// Failed to parse as JSON.
137    #[cfg(feature = "json_config")]
138    #[error("invalid json")]
139    InvalidJson(#[source] serde_json::Error),
140
141    /// Failed to parse as YAML.
142    #[cfg(feature = "yaml_config")]
143    #[error("invalid yaml")]
144    InvalidYaml(#[source] serde_yaml::Error),
145
146    /// Failed to parse the given format because it was disabled at compile-time.
147    #[error("config format disabled: {}", format)]
148    ConfigFormatDisabled {
149        /// The disabled file format.
150        format: &'static str,
151    },
152
153    /// Could not identify the given file format.
154    #[error("config format unknown: {}", format)]
155    UnknownConfigFormat {
156        /// The unknown file extension.
157        format: String,
158    },
159
160    /// File was missing an extension to identify file format.
161    #[error("missing format extension")]
162    MissingExtension,
163
164    /// Configuration does not specify a nickname.
165    #[error("nickname not specified")]
166    NicknameNotSpecified,
167
168    /// Configuration does not specify a server.
169    #[error("server not specified")]
170    ServerNotSpecified,
171
172    /// The specified file could not be read.
173    #[error("could not read file {}", file)]
174    FileMissing {
175        /// The supposed location of the file.
176        file: String,
177    },
178}
179
180/// A wrapper that combines toml's serialization and deserialization errors.
181#[cfg(feature = "toml_config")]
182#[derive(Debug, Error)]
183pub enum TomlError {
184    /// A TOML deserialization error.
185    #[error("deserialization failed")]
186    Read(#[source] toml::de::Error),
187    /// A TOML serialization error.
188    #[error("serialization failed")]
189    Write(#[source] toml::ser::Error),
190}
191
192impl From<ProtocolError> for Error {
193    fn from(e: ProtocolError) -> Error {
194        match e {
195            ProtocolError::Io(e) => Error::Io(e),
196            ProtocolError::InvalidMessage { string, cause } => {
197                Error::InvalidMessage { string, cause }
198            }
199        }
200    }
201}
202
203impl<T> From<SendError<T>> for Error {
204    fn from(_: SendError<T>) -> Error {
205        Error::AsyncChannelClosed
206    }
207}
208
209impl<T> From<TrySendError<T>> for Error {
210    fn from(_: TrySendError<T>) -> Error {
211        Error::AsyncChannelClosed
212    }
213}