fundamentum_edge_mcu_http_client/
http_client_error.rs

1use core::num::ParseIntError;
2
3use displaydoc::Display;
4use serde_json_core::de;
5use thiserror_no_std::Error;
6
7use crate::{http_handler::HttpHandler, models::StatusCode};
8
9/// Errors that might get returned by the [`HttpClient`](crate::HttpClient).
10//
11// TODO: ASP00009-1807: The error types of the HttpClient might not rely on the HttpHandler directly
12#[derive(Error, Display)]
13#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
14#[cfg_attr(feature = "log", derive(defmt::Format))]
15pub enum HttpClientError<H: HttpHandler> {
16    /// Cannot serialize the body because the buffer is full: {0}
17    SerializationBufferFull(usize),
18    /// Cannot serialize the body
19    Serialization,
20    /// Cannot convert UTF-8 characters: Valid up to {0}
21    Utf8Conversion(usize),
22    /// Failed to send HTTPS request
23    SendRequest(H::Error),
24    /// No status code found in the HTTP response
25    NoStatusCode,
26    /// Cannot parse the HTTP response: {0:?}
27    #[cfg(feature = "log")]
28    ParseHttp(#[defmt(Debug2Format)] httparse::Error),
29    /// Cannot parse the HTTP response
30    #[cfg(not(feature = "log"))]
31    ParseHttp(httparse::Error),
32    /// The HTTPS response is only partial
33    PartialHttpRequest,
34    /// No content header in response
35    NoContentHeader,
36    /// Cannot convert &[u8] buffer into a 'usize': {0:?}
37    #[cfg(feature = "log")]
38    ContentLengthConversion(#[defmt(Debug2Format)] ParseIntError),
39    #[cfg(not(feature = "log"))]
40    /// Cannot convert &[u8] buffer into a 'usize'
41    ContentLengthConversion(ParseIntError),
42    /// Cannot deserialize the body into the provided type {0:?}
43    #[cfg(feature = "log")]
44    DeserializationFailed(#[defmt(Debug2Format)] de::Error),
45    /// Cannot deserialize the body into the provided type
46    #[cfg(not(feature = "log"))]
47    DeserializationFailed(de::Error),
48    /// Request Might have failed: no "status" field found
49    MissingStatusField,
50    /// Request succeeded but no "data" field found
51    MissingDataField,
52    /// Request failed and no "message" field found
53    FailedAndMissingMessageField,
54    /// Error coming from the Api with message (message stored in [`HttpClientErrorWrapper`])
55    GenericApiError(StatusCode),
56}
57
58/// Errors with the error message returned by [`HttpClient`](crate::HttpClient).
59///
60/// ### Note
61///
62/// This enum is created because there cannot be a lifetime on [`HttpClientError`]
63/// ; the client must be able to handle the error in `start()`, which cannot
64/// be achieved with the lifetime bounded to a buffer in `main()`.
65#[derive(Error, Display)]
66#[cfg_attr(test, derive(Debug, PartialEq))]
67#[cfg_attr(feature = "log", derive(defmt::Format))]
68pub enum HttpClientErrorWrapper<'a, H: HttpHandler> {
69    /// Other errors from [`HttpClientError`].
70    OtherErrors(#[from] HttpClientError<H>),
71    /// Error coming from the API with message.
72    GenericApiError {
73        /// Error message from the Fundamentum API.
74        message: &'a str,
75        /// Status code received.
76        status_code: StatusCode,
77    },
78}
79
80impl<H: HttpHandler> From<HttpClientErrorWrapper<'_, H>> for HttpClientError<H> {
81    fn from(err: HttpClientErrorWrapper<H>) -> Self {
82        match err {
83            HttpClientErrorWrapper::OtherErrors(e) => e,
84            HttpClientErrorWrapper::GenericApiError { status_code, .. } => {
85                Self::GenericApiError(status_code)
86            }
87        }
88    }
89}