skyway_webrtc_gateway_api/
error.rs

1use reqwest;
2use serde::ser::SerializeStruct;
3use serde::{Deserialize, Serialize, Serializer};
4use thiserror::Error;
5
6/// Enum of errors in this crate.
7#[derive(Debug, Error)]
8pub enum Error {
9    #[error("{}", 0)]
10    IOError { error: ::std::io::ErrorKind },
11    #[error("{}", 0)]
12    Utf8Error { error: ::std::str::Utf8Error },
13    #[error("{}", 0)]
14    SerdeError { error: serde_json::Error },
15    #[error("{}", 0)]
16    ReqwestError(#[from] reqwest::Error),
17    #[error("{}", 0)]
18    AddrParseError(#[from] std::net::AddrParseError),
19    #[error("{}", 0)]
20    LocalError(String),
21}
22
23impl Error {
24    /// Create error message to show internal error
25    #[allow(dead_code)]
26    pub fn create_local_error(message: &str) -> Error {
27        Error::LocalError(message.into())
28    }
29}
30
31impl Serialize for Error {
32    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
33    where
34        S: Serializer,
35    {
36        let mut state = serializer.serialize_struct("Error", 2)?;
37        match self {
38            Error::IOError { error } => {
39                state.serialize_field("reason", "IoError")?;
40                state.serialize_field(
41                    "message",
42                    &format!("{}", std::io::Error::from(error.clone())),
43                )?;
44            }
45            Error::Utf8Error { error } => {
46                state.serialize_field("reason", "IoError")?;
47                state.serialize_field("message", &format!("{}", error))?;
48            }
49            Error::SerdeError { error } => {
50                state.serialize_field("reason", "JsonError")?;
51                state.serialize_field("message", &format!("{}", error))?;
52            }
53            Error::ReqwestError(error) => {
54                state.serialize_field("reason", "NetworkError")?;
55                state.serialize_field("message", &format!("{}", error))?;
56            }
57            Error::AddrParseError(error) => {
58                state.serialize_field("reason", "InvalidAddressError")?;
59                state.serialize_field("message", &format!("{}", error))?;
60            }
61            Error::LocalError(error) => {
62                state.serialize_field("reason", "InternalError")?;
63                state.serialize_field("message", &format!("{}", error))?;
64            }
65        }
66        state.end()
67    }
68}
69
70#[cfg(test)]
71mod serialize_error {
72    use serde_json::Value;
73
74    use super::*;
75    use std::net::IpAddr;
76
77    #[test]
78    fn io_error() {
79        let expected = serde_json::from_str::<Value>(
80            "{\"message\":\"address in use\", \"reason\":\"IoError\"}",
81        )
82        .unwrap();
83
84        let error = Error::IOError {
85            error: std::io::ErrorKind::AddrInUse,
86        };
87        let message = serde_json::to_string(&error).unwrap();
88        let message = serde_json::from_str::<Value>(&message).unwrap();
89
90        assert_eq!(expected, message);
91    }
92
93    #[test]
94    fn utf8_error() {
95        use std::str;
96
97        let expected = serde_json::from_str::<Value>(
98            "{\"reason\":\"IoError\",\"message\":\"invalid utf-8 sequence of 1 bytes from index 1\"}"
99        ).unwrap();
100
101        let wrong_binary = vec![0, 159, 146, 150];
102        let utf8_error_message = str::from_utf8(&wrong_binary).unwrap_err();
103        let utf8_error_enum = Error::Utf8Error {
104            error: utf8_error_message,
105        };
106        let message = serde_json::to_string(&utf8_error_enum).unwrap();
107        let message = serde_json::from_str::<Value>(&message).unwrap();
108
109        assert_eq!(expected, message);
110    }
111
112    #[test]
113    fn serde_error() {
114        let expected = serde_json::from_str::<Value>(
115            "{\"reason\":\"JsonError\", \"message\":\"expected value at line 1 column 1\"}",
116        )
117        .unwrap();
118
119        let serde_error = serde_json::from_str::<Value>("invalid json").unwrap_err();
120        let serde_error_enum = Error::SerdeError { error: serde_error };
121        let message = serde_json::to_string(&serde_error_enum).unwrap();
122        let message = serde_json::from_str::<Value>(&message).unwrap();
123
124        assert_eq!(expected, message);
125    }
126
127    #[tokio::test]
128    async fn reqwest_error() {
129        let expected = serde_json::from_str::<Value>(
130            r#"{
131                "reason":"NetworkError",
132                "message": "error sending request for url (http://localhost:0/): error trying to connect: tcp connect error: Connection refused (os error 111)"
133               }"#
134        )
135        .unwrap();
136
137        let reqwest_error = reqwest::get("http://localhost:0").await.unwrap_err();
138        let reqwest_error_enum = Error::ReqwestError(reqwest_error);
139        let message = serde_json::to_string(&reqwest_error_enum).unwrap();
140        let message = serde_json::from_str::<Value>(&message).unwrap();
141
142        assert_eq!(expected, message);
143    }
144
145    #[test]
146    fn address_error() {
147        let expected = serde_json::from_str::<Value>(
148            r#"{
149                "reason":"InvalidAddressError", 
150                "message":"invalid IP address syntax"
151              }"#,
152        )
153        .unwrap();
154
155        let result: Result<IpAddr, _> = "invalid addr".parse();
156        let addr_error_enum = Error::AddrParseError(result.unwrap_err());
157        let message = serde_json::to_string(&addr_error_enum).unwrap();
158        let message = serde_json::from_str::<Value>(&message).unwrap();
159
160        assert_eq!(expected, message);
161    }
162
163    #[test]
164    fn internal_error() {
165        let expected = serde_json::from_str::<Value>(
166            r#"{
167                "reason":"InternalError", 
168                "message":"error"
169              }"#,
170        )
171        .unwrap();
172
173        let internal_error_enum = Error::create_local_error("error");
174        let message = serde_json::to_string(&internal_error_enum).unwrap();
175        let message = serde_json::from_str::<Value>(&message).unwrap();
176
177        assert_eq!(expected, message);
178    }
179}
180
181impl PartialEq for Error {
182    fn eq(&self, other: &Self) -> bool {
183        match (serde_json::to_string(self), serde_json::to_string(other)) {
184            (Ok(a), Ok(b)) => a == b,
185            _ => false,
186        }
187    }
188}
189
190/// Error response from some APIs.
191#[derive(Serialize, Deserialize, Debug, Clone, PartialOrd, PartialEq)]
192pub(crate) struct ErrorResponse {
193    /// Shows where this Json is from.
194    pub command_type: String,
195    /// Shows errors
196    pub params: Errors,
197}
198
199/// Shows errors
200#[derive(Serialize, Deserialize, Debug, Clone, PartialOrd, PartialEq)]
201pub(crate) struct Errors {
202    /// Shows errors
203    pub errors: Vec<ErrorItem>,
204}
205
206/// Shows errors
207#[derive(Serialize, Deserialize, Debug, Clone, PartialOrd, PartialEq)]
208pub(crate) struct ErrorItem {
209    /// Error kind
210    pub field: String,
211    /// Error detail message
212    pub message: String,
213}