microsoft_cognitive_computer_vision/operations/
common.rs

1use core::fmt;
2
3use http_api_client_endpoint::{
4    http::{Error as HttpError, StatusCode},
5    Body, Response,
6};
7use serde::{de::DeserializeOwned, Deserialize, Serialize};
8use serde_json::Error as SerdeJsonError;
9use url::ParseError as UrlParseError;
10
11//
12//
13//
14#[derive(Debug, Clone)]
15pub enum EndpointRet<T>
16where
17    T: fmt::Debug + Clone,
18{
19    Ok(T),
20    Other((StatusCode, Result<EndpointResponseBodyErrJson, Body>)),
21}
22
23//
24//
25//
26#[derive(thiserror::Error, Debug)]
27pub enum EndpointError {
28    #[error("MakeRequestUrlFailed {0}")]
29    MakeRequestUrlFailed(UrlParseError),
30    #[error("ImageInputToRequestBodyFailed {0}")]
31    ImageInputToRequestBodyFailed(String),
32    #[error("MakeRequestFailed {0}")]
33    MakeRequestFailed(HttpError),
34    #[error("DeResponseBodyOkJsonFailed {0}")]
35    DeResponseBodyOkJsonFailed(SerdeJsonError),
36}
37
38//
39//
40//
41#[derive(Serialize, Deserialize, Debug, Clone)]
42pub struct EndpointResponseBodyErrJson {
43    pub error: EndpointResponseBodyErrJsonError,
44}
45
46#[derive(Serialize, Deserialize, Debug, Clone)]
47pub struct EndpointResponseBodyErrJsonError {
48    pub code: String,
49    pub message: String,
50    pub innererror: Option<EndpointResponseBodyErrJsonErrorInnererror>,
51}
52
53#[derive(Serialize, Deserialize, Debug, Clone)]
54pub struct EndpointResponseBodyErrJsonErrorInnererror {
55    pub code: String,
56    pub message: String,
57}
58
59//
60//
61//
62pub fn endpoint_parse_response<T>(response: Response<Body>) -> Result<EndpointRet<T>, EndpointError>
63where
64    T: fmt::Debug + Clone + DeserializeOwned,
65{
66    let status = response.status();
67    match status {
68        StatusCode::OK => {
69            let ok_json = serde_json::from_slice::<T>(response.body())
70                .map_err(EndpointError::DeResponseBodyOkJsonFailed)?;
71
72            Ok(EndpointRet::Ok(ok_json))
73        }
74        StatusCode::METHOD_NOT_ALLOWED => {
75            match serde_json::from_slice::<EndpointResponseBodyErrJsonError>(response.body()) {
76                Ok(err_json) => Ok(EndpointRet::Other((
77                    status,
78                    Ok(EndpointResponseBodyErrJson { error: err_json }),
79                ))),
80                Err(_) => Ok(EndpointRet::Other((
81                    status,
82                    Err(response.body().to_owned()),
83                ))),
84            }
85        }
86        status => match serde_json::from_slice::<EndpointResponseBodyErrJson>(response.body()) {
87            Ok(err_json) => Ok(EndpointRet::Other((status, Ok(err_json)))),
88            Err(_) => Ok(EndpointRet::Other((
89                status,
90                Err(response.body().to_owned()),
91            ))),
92        },
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99
100    #[test]
101    fn de_response_body_err_json() {
102        match serde_json::from_str::<EndpointResponseBodyErrJson>(include_str!(
103            "../../tests/response_body_files/detect_objects_err__401.json"
104        )) {
105            Ok(err_json) => {
106                assert_eq!(err_json.error.code, "401");
107            }
108            Err(err) => panic!("{}", err),
109        }
110    }
111}