Skip to main content

ntex_amqp/client/
error.rs

1use ntex_error::{ErrorDiagnostic, ErrorType};
2use ntex_util::future::Either;
3
4use crate::codec::{AmqpCodecError, AmqpFrame, ProtocolIdError, protocol};
5
6/// Errors which can occur when attempting to handle amqp client connection.
7#[derive(Debug, thiserror::Error)]
8pub enum ConnectError {
9    /// Amqp codec error
10    #[error("Amqp codec error: {:?}", _0)]
11    Codec(#[from] AmqpCodecError),
12    /// Handshake timeout
13    #[error("Handshake timeout")]
14    HandshakeTimeout,
15    /// Protocol negotiation error
16    #[error("Peer disconnected")]
17    ProtocolNegotiation(#[from] ProtocolIdError),
18    /// Expected open frame
19    #[error("Expect open frame, got: {:?}", _0)]
20    ExpectOpenFrame(Box<AmqpFrame>),
21    /// Peer disconnected
22    #[error("Sasl error code: {:?}", _0)]
23    Sasl(protocol::SaslCode),
24    #[error("Peer disconnected")]
25    Disconnected,
26    /// Connect error
27    #[error("Connect error: {}", _0)]
28    Connect(#[from] ntex_net::connect::ConnectError),
29    /// Unexpected io error
30    #[error("Io error: {}", _0)]
31    Io(#[from] std::io::Error),
32}
33
34impl Clone for ConnectError {
35    fn clone(&self) -> Self {
36        match self {
37            ConnectError::Codec(err) => ConnectError::Codec(err.clone()),
38            ConnectError::HandshakeTimeout => ConnectError::HandshakeTimeout,
39            ConnectError::ProtocolNegotiation(err) => {
40                ConnectError::ProtocolNegotiation(err.clone())
41            }
42            ConnectError::ExpectOpenFrame(frame) => ConnectError::ExpectOpenFrame(frame.clone()),
43            ConnectError::Sasl(err) => ConnectError::Sasl(*err),
44            ConnectError::Disconnected => ConnectError::Disconnected,
45            ConnectError::Connect(err) => ConnectError::Connect(err.clone()),
46            ConnectError::Io(err) => {
47                ConnectError::Io(std::io::Error::new(err.kind(), format!("{err}")))
48            }
49        }
50    }
51}
52
53impl ErrorDiagnostic for ConnectError {
54    type Kind = ErrorType;
55
56    fn kind(&self) -> Self::Kind {
57        if let ConnectError::Sasl(err) = self
58            && matches!(err, protocol::SaslCode::Auth | protocol::SaslCode::SysPerm)
59        {
60            ErrorType::Client
61        } else {
62            ErrorType::Service
63        }
64    }
65}
66
67impl From<Either<AmqpCodecError, std::io::Error>> for ConnectError {
68    fn from(err: Either<AmqpCodecError, std::io::Error>) -> Self {
69        match err {
70            Either::Left(err) => ConnectError::Codec(err),
71            Either::Right(err) => ConnectError::Io(err),
72        }
73    }
74}
75
76impl From<Either<ProtocolIdError, std::io::Error>> for ConnectError {
77    fn from(err: Either<ProtocolIdError, std::io::Error>) -> Self {
78        match err {
79            Either::Left(err) => ConnectError::ProtocolNegotiation(err),
80            Either::Right(err) => ConnectError::Io(err),
81        }
82    }
83}