Skip to main content

nanofish_client/
error.rs

1use embassy_net_08 as embassy_net;
2#[cfg(feature = "tls")]
3use embedded_tls_018 as embedded_tls;
4/// Errors that can occur during HTTP operations
5///
6/// This enum represents all possible errors that can be returned by the HTTP client
7/// during various stages of request processing, from URL parsing to connection
8/// establishment and response handling.
9#[derive(Debug)]
10/// All possible errors returned by the HTTP client.
11pub enum Error {
12    /// The provided URL was invalid or malformed
13    InvalidUrl,
14    /// DNS resolution failed
15    DnsError(embassy_net::dns::Error),
16    /// No IP addresses were returned by DNS resolution
17    IpAddressEmpty,
18    /// Failed to establish a TCP connection
19    ConnectionError(embassy_net::tcp::ConnectError),
20    /// TCP communication error
21    TcpError(embassy_net::tcp::Error),
22    /// No response was received from the server
23    NoResponse,
24    /// The server's response could not be parsed
25    InvalidResponse(&'static str),
26    /// This error occurs when there is an issue with the TLS handshake or communication.
27    #[cfg(feature = "tls")]
28    TlsError(embedded_tls::TlsError),
29    /// Scheme not supported
30    UnsupportedScheme(&'static str),
31    /// Header error, e.g. too long name or value
32    HeaderError(&'static str),
33    /// Invalid status code received from the server
34    InvalidStatusCode,
35}
36
37impl defmt::Format for Error {
38    fn format(&self, fmt: defmt::Formatter) {
39        defmt::write!(fmt, "{:?}", defmt::Debug2Format(self));
40    }
41}
42
43impl From<embassy_net::dns::Error> for Error {
44    fn from(err: embassy_net::dns::Error) -> Self {
45        Error::DnsError(err)
46    }
47}
48
49impl From<embassy_net::tcp::ConnectError> for Error {
50    fn from(err: embassy_net::tcp::ConnectError) -> Self {
51        Error::ConnectionError(err)
52    }
53}
54
55impl From<embassy_net::tcp::Error> for Error {
56    fn from(err: embassy_net::tcp::Error) -> Self {
57        Error::TcpError(err)
58    }
59}
60
61#[cfg(feature = "tls")]
62impl From<embedded_tls::TlsError> for Error {
63    fn from(err: embedded_tls::TlsError) -> Self {
64        Error::TlsError(err)
65    }
66}
67
68impl core::fmt::Display for Error {
69    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
70        match self {
71            Error::InvalidUrl => write!(f, "Invalid URL"),
72            Error::DnsError(_) => write!(f, "DNS resolution failed"),
73            Error::IpAddressEmpty => write!(f, "No IP addresses returned by DNS"),
74            Error::ConnectionError(_) => write!(f, "Failed to establish TCP connection"),
75            Error::TcpError(_) => write!(f, "TCP communication error"),
76            Error::NoResponse => write!(f, "No response received from server"),
77            Error::InvalidResponse(msg) => write!(f, "Invalid response: {msg}"),
78            #[cfg(feature = "tls")]
79            Error::TlsError(_) => write!(f, "TLS error occurred"),
80            Error::UnsupportedScheme(scheme) => write!(f, "Unsupported scheme: {scheme}"),
81            Error::HeaderError(msg) => write!(f, "Header error: {msg}"),
82            Error::InvalidStatusCode => write!(f, "Invalid status code"),
83        }
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90    use embassy_net::dns;
91    use embassy_net::tcp;
92
93    #[test]
94    fn test_error_display() {
95        let e = Error::InvalidUrl;
96        assert_eq!(format!("{e}"), "Invalid URL");
97        let e = Error::IpAddressEmpty;
98        assert_eq!(format!("{e}"), "No IP addresses returned by DNS");
99        let e = Error::NoResponse;
100        assert_eq!(format!("{e}"), "No response received from server");
101        let e = Error::InvalidResponse("bad");
102        assert_eq!(format!("{e}"), "Invalid response: bad");
103        let e = Error::UnsupportedScheme("ftp");
104        assert_eq!(format!("{e}"), "Unsupported scheme: ftp");
105        let e = Error::HeaderError("too long");
106        assert_eq!(format!("{e}"), "Header error: too long");
107        let e = Error::InvalidStatusCode;
108        assert_eq!(format!("{e}"), "Invalid status code");
109    }
110
111    #[test]
112    fn test_from_dns_error() {
113        let dns_err = dns::Error::InvalidName;
114        let err: Error = dns_err.into();
115        match err {
116            Error::DnsError(_) => {}
117            _ => panic!("Expected DnsError variant"),
118        }
119    }
120
121    #[test]
122    fn test_from_tcp_error() {
123        let tcp_err = tcp::Error::ConnectionReset;
124        let err: Error = tcp_err.into();
125        match err {
126            Error::TcpError(_) => {}
127            _ => panic!("Expected TcpError variant"),
128        }
129    }
130}