skyway_webrtc_gateway_api/
error.rs1use reqwest;
2use serde::ser::SerializeStruct;
3use serde::{Deserialize, Serialize, Serializer};
4use thiserror::Error;
5
6#[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 #[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#[derive(Serialize, Deserialize, Debug, Clone, PartialOrd, PartialEq)]
192pub(crate) struct ErrorResponse {
193 pub command_type: String,
195 pub params: Errors,
197}
198
199#[derive(Serialize, Deserialize, Debug, Clone, PartialOrd, PartialEq)]
201pub(crate) struct Errors {
202 pub errors: Vec<ErrorItem>,
204}
205
206#[derive(Serialize, Deserialize, Debug, Clone, PartialOrd, PartialEq)]
208pub(crate) struct ErrorItem {
209 pub field: String,
211 pub message: String,
213}