Skip to main content

rustenium_bidi_definitions/
base.rs

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}