1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4use serde::Deserializer;
5
6use crate::{Command, Event};
7
8fn float_or_int_to_u64<'de, D>(deserializer: D) -> Result<u64, D::Error>
9where
10 D: Deserializer<'de>,
11{
12 let value = serde_json::Value::deserialize(deserializer)?;
13
14 match value {
15 serde_json::Value::Number(num) => {
16 if let Some(i) = num.as_u64() {
17 Ok(i)
18 } else if let Some(f) = num.as_f64() {
19 Ok(f as u64)
20 } else {
21 Err(serde::de::Error::custom("Invalid number"))
22 }
23 }
24 _ => Err(serde::de::Error::custom("Expected a number")),
25 }
26}
27
28fn option_float_or_int_to_u64<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
29where
30 D: Deserializer<'de>,
31{
32 let value = serde_json::Value::deserialize(deserializer)?;
33
34 if value.is_null() {
35 return Ok(None);
36 }
37
38 match value {
39 serde_json::Value::Number(num) => {
40 if let Some(i) = num.as_u64() {
41 Ok(Some(i))
42 } else if let Some(f) = num.as_f64() {
43 Ok(Some(f as u64))
44 } else {
45 Err(serde::de::Error::custom("Invalid number"))
46 }
47 }
48 _ => Err(serde::de::Error::custom("Expected a number")),
49 }
50}
51
52fn deserialize_empty_map<'de, D>(deserializer: D) -> Result<Extensible, D::Error>
53where
54 D: serde::Deserializer<'de>,
55{
56 let map = Extensible::deserialize(deserializer)?;
57
58 if map.is_empty() {
59 Ok(map)
60 } else {
61 Err(serde::de::Error::custom("expected empty object"))
62 }
63}
64
65pub type Extensible = HashMap<String, serde_json::Value>;
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct CommandMessage {
69 #[serde(rename = "id")]
70 pub id: u64,
71 #[serde(flatten)]
72 pub command_data: Command,
73 #[serde(flatten)]
74 pub extensible: Extensible,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct EmptyParams {
79 #[serde(flatten, deserialize_with = "deserialize_empty_map")]
80 pub extensible: Extensible,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
84#[serde(untagged)]
85pub enum Message {
86 ErrorResponse(ErrorResponse),
87 CommandResponse(CommandResponse),
88 Event(EventResponse),
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize)]
92pub struct CommandResponse {
93 #[serde(rename = "type")]
94 pub r#type: SuccessEnum,
95 #[serde(rename = "id")]
96 #[serde(deserialize_with = "float_or_int_to_u64")]
97 pub id: u64,
98 #[serde(rename = "result")]
99 pub result: serde_json::Value,
100 #[serde(flatten)]
101 pub extensible: Extensible,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
105pub struct ErrorResponse {
106 #[serde(rename = "type")]
107 pub r#type: ErrorEnum,
108 #[serde(rename = "id")]
109 #[serde(deserialize_with = "option_float_or_int_to_u64")]
110 pub id: Option<u64>,
111 #[serde(rename = "error")]
112 pub error: ErrorCode,
113 #[serde(rename = "message")]
114 pub message: String,
115 #[serde(rename = "stacktrace")]
116 #[serde(skip_serializing_if = "Option::is_none")]
117 pub stacktrace: Option<String>,
118 #[serde(flatten)]
119 pub extensible: Extensible,
120}
121
122impl std::fmt::Display for ErrorResponse {
123 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124 write!(
125 f,
126 "Error[{}]: {} (ID: {}){}",
127 self.error,
128 self.message,
129 self.id.map_or("None".to_string(), |id| id.to_string()),
130 self.stacktrace
131 .as_ref()
132 .map_or("".to_string(), |st| format!("\nStacktrace:\n{}", st))
133 )
134 }
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct EventResponse {
139 #[serde(rename = "type")]
140 pub r#type: EventEnum,
141 #[serde(flatten)]
142 pub event_data: Event,
143 #[serde(flatten)]
144 pub extensible: Extensible,
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
148pub enum ErrorCode {
149 #[serde(rename = "invalid argument")]
150 InvalidArgument,
151 #[serde(rename = "invalid selector")]
152 InvalidSelector,
153 #[serde(rename = "invalid session id")]
154 InvalidSessionId,
155 #[serde(rename = "invalid web extension")]
156 InvalidWebExtension,
157 #[serde(rename = "move target out of bounds")]
158 MoveTargetOutOfBounds,
159 #[serde(rename = "no such alert")]
160 NoSuchAlert,
161 #[serde(rename = "no such network collector")]
162 NoSuchNetworkCollector,
163 #[serde(rename = "no such element")]
164 NoSuchElement,
165 #[serde(rename = "no such frame")]
166 NoSuchFrame,
167 #[serde(rename = "no such handle")]
168 NoSuchHandle,
169 #[serde(rename = "no such history entry")]
170 NoSuchHistoryEntry,
171 #[serde(rename = "no such intercept")]
172 NoSuchIntercept,
173 #[serde(rename = "no such network data")]
174 NoSuchNetworkData,
175 #[serde(rename = "no such node")]
176 NoSuchNode,
177 #[serde(rename = "no such request")]
178 NoSuchRequest,
179 #[serde(rename = "no such script")]
180 NoSuchScript,
181 #[serde(rename = "no such storage partition")]
182 NoSuchStoragePartition,
183 #[serde(rename = "no such user context")]
184 NoSuchUserContext,
185 #[serde(rename = "no such web extension")]
186 NoSuchWebExtension,
187 #[serde(rename = "session not created")]
188 SessionNotCreated,
189 #[serde(rename = "unable to capture screen")]
190 UnableToCaptureScreen,
191 #[serde(rename = "unable to close drivers")]
192 UnableToCloseBrowser,
193 #[serde(rename = "unable to set cookie")]
194 UnableToSetCookie,
195 #[serde(rename = "unable to set file input")]
196 UnableToSetFileInput,
197 #[serde(rename = "unavailable network data")]
198 UnavailableNetworkData,
199 #[serde(rename = "underspecified storage partition")]
200 UnderspecifiedStoragePartition,
201 #[serde(rename = "unknown command")]
202 UnknownCommand,
203 #[serde(rename = "unknown error")]
204 UnknownError,
205 #[serde(rename = "unsupported operation")]
206 UnsupportedOperation,
207}
208
209impl std::fmt::Display for ErrorCode {
210 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
211 match self {
212 ErrorCode::InvalidArgument => write!(f, "invalid argument"),
213 ErrorCode::InvalidSelector => write!(f, "invalid selector"),
214 ErrorCode::InvalidSessionId => write!(f, "invalid session id"),
215 ErrorCode::InvalidWebExtension => write!(f, "invalid web extension"),
216 ErrorCode::MoveTargetOutOfBounds => write!(f, "move target out of bounds"),
217 ErrorCode::NoSuchAlert => write!(f, "no such alert"),
218 ErrorCode::NoSuchNetworkCollector => write!(f, "no such network collector"),
219 ErrorCode::NoSuchElement => write!(f, "no such element"),
220 ErrorCode::NoSuchFrame => write!(f, "no such frame"),
221 ErrorCode::NoSuchHandle => write!(f, "no such handle"),
222 ErrorCode::NoSuchHistoryEntry => write!(f, "no such history entry"),
223 ErrorCode::NoSuchIntercept => write!(f, "no such intercept"),
224 ErrorCode::NoSuchNetworkData => write!(f, "no such network data"),
225 ErrorCode::NoSuchNode => write!(f, "no such node"),
226 ErrorCode::NoSuchRequest => write!(f, "no such request"),
227 ErrorCode::NoSuchScript => write!(f, "no such script"),
228 ErrorCode::NoSuchStoragePartition => write!(f, "no such storage partition"),
229 ErrorCode::NoSuchUserContext => write!(f, "no such user context"),
230 ErrorCode::NoSuchWebExtension => write!(f, "no such web extension"),
231 ErrorCode::SessionNotCreated => write!(f, "session not created"),
232 ErrorCode::UnableToCaptureScreen => write!(f, "unable to capture screen"),
233 ErrorCode::UnableToCloseBrowser => write!(f, "unable to close drivers"),
234 ErrorCode::UnableToSetCookie => write!(f, "unable to set cookie"),
235 ErrorCode::UnableToSetFileInput => write!(f, "unable to set file input"),
236 ErrorCode::UnavailableNetworkData => write!(f, "unavailable network data"),
237 ErrorCode::UnderspecifiedStoragePartition => {
238 write!(f, "underspecified storage partition")
239 }
240 ErrorCode::UnknownCommand => write!(f, "unknown command"),
241 ErrorCode::UnknownError => write!(f, "unknown error"),
242 ErrorCode::UnsupportedOperation => write!(f, "unsupported operation"),
243 }
244 }
245}
246
247#[derive(Debug, Clone, Serialize, Deserialize)]
248pub enum SuccessEnum {
249 #[serde(rename = "success")]
250 Success,
251}
252
253#[derive(Debug, Clone, Serialize, Deserialize)]
254pub enum ErrorEnum {
255 #[serde(rename = "error")]
256 Error,
257}
258
259#[derive(Debug, Clone, Serialize, Deserialize)]
260pub enum EventEnum {
261 #[serde(rename = "event")]
262 Event,
263}