Skip to main content

ntex_net/connect/
error.rs

1use std::io::{self, ErrorKind};
2
3use ntex_error::{ErrorDiagnostic, ErrorType};
4
5#[derive(thiserror::Error, Debug, Copy, Clone)]
6pub enum ConnectServiceError {
7    /// Cannot create connect service
8    #[error("Cannot create connect service")]
9    CannotCreateService,
10}
11
12#[derive(thiserror::Error, Debug)]
13pub enum ConnectError {
14    /// Failed to resolve the hostname
15    #[error("Failed resolving hostname: {0}")]
16    Resolver(io::Error),
17
18    /// No dns records
19    #[error("No dns records found for the input")]
20    NoRecords,
21
22    /// Invalid input
23    #[error("Invalid input")]
24    InvalidInput,
25
26    /// Unresolved host name
27    #[error("Connector received `Connect` method with unresolved host")]
28    Unresolved,
29
30    /// Connection io error
31    #[error("{0}")]
32    Io(#[from] io::Error),
33}
34
35impl Clone for ConnectError {
36    fn clone(&self) -> Self {
37        match self {
38            ConnectError::Resolver(err) => {
39                ConnectError::Resolver(io::Error::new(err.kind(), format!("{err}")))
40            }
41            ConnectError::NoRecords => ConnectError::NoRecords,
42            ConnectError::InvalidInput => ConnectError::InvalidInput,
43            ConnectError::Unresolved => ConnectError::Unresolved,
44            ConnectError::Io(err) => {
45                ConnectError::Io(io::Error::new(err.kind(), format!("{err}")))
46            }
47        }
48    }
49}
50
51impl From<ConnectServiceError> for io::Error {
52    fn from(err: ConnectServiceError) -> io::Error {
53        io::Error::other(err)
54    }
55}
56
57impl ErrorDiagnostic for ConnectError {
58    type Kind = ErrorType;
59
60    fn kind(&self) -> Self::Kind {
61        match self {
62            ConnectError::InvalidInput => ErrorType::Client,
63            ConnectError::Resolver(_)
64            | ConnectError::NoRecords
65            | ConnectError::Unresolved => ErrorType::Service,
66            ConnectError::Io(err) => {
67                if matches!(
68                    err.kind(),
69                    ErrorKind::InvalidInput
70                        | ErrorKind::AddrNotAvailable
71                        | ErrorKind::Unsupported
72                ) {
73                    ErrorType::Client
74                } else {
75                    ErrorType::Service
76                }
77            }
78        }
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    #[allow(clippy::redundant_clone)]
88    fn connect_error_clone() {
89        let _ = ConnectError::Resolver(io::Error::other("test")).clone();
90        let _ = ConnectError::NoRecords.clone();
91        let _ = ConnectError::InvalidInput.clone();
92        let _ = ConnectError::Unresolved.clone();
93        let _ = ConnectError::Io(io::Error::other("test")).clone();
94    }
95
96    #[test]
97    fn error_diagnostic() {
98        assert_eq!(ConnectError::InvalidInput.kind(), ErrorType::Client);
99        assert_eq!(
100            ConnectError::Resolver(io::Error::other("test")).kind(),
101            ErrorType::Service
102        );
103        assert_eq!(
104            ConnectError::Io(io::Error::new(ErrorKind::InvalidInput, "test")).kind(),
105            ErrorType::Client
106        );
107        assert_eq!(
108            ConnectError::Io(io::Error::other("test")).kind(),
109            ErrorType::Service
110        );
111    }
112}