playwright/imp/core/
message.rs

1pub(crate) mod de;
2pub(crate) mod ser;
3
4use crate::imp::core::Error;
5use serde::{Deserialize, Deserializer};
6use serde_json::{map::Map, value::Value};
7use strong::*;
8
9#[derive(Debug, Serialize)]
10pub(crate) struct Req<'a, 'b> {
11    #[serde(default)]
12    pub(crate) id: i32,
13    pub(crate) guid: &'a S<Guid>,
14    #[serde(default)]
15    pub(crate) method: &'b S<Method>,
16    #[serde(default)]
17    pub(crate) params: Map<String, Value>,
18    /// Metadata is required by Playwright 1.50+
19    #[serde(default)]
20    pub(crate) metadata: Map<String, Value>,
21}
22
23#[derive(Debug, Deserialize, Clone)]
24#[serde(untagged)]
25pub(crate) enum Res {
26    Result(ResResult),
27    Initial(ResInitial),
28}
29
30#[derive(Debug, Clone)]
31pub(crate) struct ResResult {
32    pub(crate) id: i32,
33    pub(crate) body: Result<Value, ErrorMessage>,
34}
35
36impl<'de> Deserialize<'de> for ResResult {
37    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
38    where
39        D: Deserializer<'de>,
40    {
41        #[derive(Deserialize)]
42        struct ResponseResultImpl {
43            id: i32,
44            result: Option<Value>,
45            error: Option<ErrorWrap>,
46        }
47        let ResponseResultImpl { id, result, error } =
48            ResponseResultImpl::deserialize(deserializer)?;
49        if let Some(ErrorWrap { error }) = error {
50            Ok(Self {
51                id,
52                body: Err(error),
53            })
54        } else if let Some(x) = result {
55            Ok(Self { id, body: Ok(x) })
56        } else {
57            Ok(Self {
58                id,
59                body: Ok(Value::default()),
60            })
61        }
62    }
63}
64
65#[derive(Debug, Deserialize, Serialize, Clone)]
66pub(crate) struct ResInitial {
67    pub(crate) guid: Str<Guid>,
68    pub(crate) method: Str<Method>,
69    #[serde(default)]
70    pub(crate) params: Map<String, Value>,
71}
72
73#[derive(Debug, Deserialize, Serialize)]
74pub(crate) struct CreateParams {
75    #[serde(rename = "type")]
76    pub(crate) typ: Str<ObjectType>,
77    pub(crate) guid: Str<Guid>,
78    #[serde(default)]
79    pub(crate) initializer: Value,
80}
81
82#[derive(Debug, Deserialize, Serialize, Clone)]
83pub(crate) struct ErrorWrap {
84    error: ErrorMessage,
85}
86
87#[derive(Debug, Deserialize, Serialize, Clone, thiserror::Error)]
88#[error("{name} {message:?}")]
89pub struct ErrorMessage {
90    pub(crate) name: String,
91    pub(crate) message: String,
92    pub(crate) stack: String,
93}
94
95#[derive(Debug, Deserialize, Serialize)]
96pub(crate) struct OnlyGuid {
97    pub(crate) guid: Str<Guid>,
98}
99
100pub(crate) enum Guid {}
101
102impl Validator for Guid {
103    type Err = std::convert::Infallible;
104}
105
106pub(crate) enum Method {}
107
108#[derive(thiserror::Error, Debug)]
109#[error("Method {0:?} validation error")]
110pub(crate) struct MethodError(String);
111
112impl Validator for Method {
113    type Err = MethodError;
114
115    fn validate(raw: &str) -> Result<(), Self::Err> {
116        if raw.is_empty() {
117            Err(MethodError(raw.to_string()))
118        } else {
119            Ok(())
120        }
121    }
122}
123
124impl Method {
125    pub(crate) fn is_create(s: &S<Self>) -> bool {
126        s.as_str() == "__create__"
127    }
128    pub(crate) fn is_dispose(s: &S<Self>) -> bool {
129        s.as_str() == "__dispose__"
130    }
131}
132
133pub(crate) enum ObjectType {}
134
135impl Validator for ObjectType {
136    type Err = std::convert::Infallible;
137}
138
139pub(crate) fn first(v: &Value) -> Option<&Value> {
140    let m: &Map<String, Value> = v.as_object()?;
141    first_object(m)
142}
143
144pub(crate) fn first_object(m: &Map<String, Value>) -> Option<&Value> {
145    if m.len() != 1 {
146        return None;
147    }
148    let v: &Value = m.values().next()?;
149    Some(v)
150}
151
152/// If {"<type>": {"guid": str}} then str
153pub(crate) fn as_only_guid(v: &Value) -> Option<&S<Guid>> {
154    // {"<type>": {"guid": str}}
155    let v: &Value = first(v)?;
156    // {"guid": str}
157    let m: &Map<String, Value> = v.as_object()?;
158    let v: &Value = m.get("guid")?;
159    let s: &str = v.as_str()?;
160    S::validate(s).ok()
161}
162
163pub(crate) fn only_guid(v: &Value) -> Result<&S<Guid>, Error> {
164    as_only_guid(v).ok_or_else(|| Error::GuidNotFound(v.clone()))
165}
166
167pub(crate) fn only_str(v: &Value) -> Result<&str, Error> {
168    let s = first(v)
169        .ok_or(Error::InvalidParams)?
170        .as_str()
171        .ok_or(Error::InvalidParams)?;
172    Ok(s)
173}
174
175pub(crate) fn maybe_only_str(v: &Value) -> Result<Option<&str>, Error> {
176    let s = match first(v) {
177        Some(s) => s.as_str().ok_or(Error::InvalidParams)?,
178        None => return Ok(None),
179    };
180    Ok(Some(s))
181}
182
183#[derive(Debug, Serialize)]
184pub(crate) struct Argument {
185    pub(crate) value: Map<String, Value>,
186    pub(crate) handles: Vec<OnlyGuid>,
187}
188
189#[derive(Debug, Deserialize)]
190pub struct DateTime {
191    d: String,
192}
193
194mod datetime {
195    use super::*;
196    #[cfg(feature = "chrono")]
197    use chrono::Utc;
198    use serde::{ser, ser::SerializeStruct};
199    use std::convert::TryFrom;
200
201    #[cfg(feature = "chrono")]
202    impl From<chrono::DateTime<Utc>> for DateTime {
203        fn from(c: chrono::DateTime<Utc>) -> DateTime {
204            Self { d: c.to_rfc3339() }
205        }
206    }
207
208    #[cfg(feature = "chrono")]
209    impl TryFrom<DateTime> for chrono::DateTime<Utc> {
210        type Error = chrono::format::ParseError;
211
212        fn try_from(d: DateTime) -> Result<chrono::DateTime<Utc>, Self::Error> {
213            let f = chrono::DateTime::parse_from_rfc3339(&d.d)?;
214            Ok(f.with_timezone(&chrono::Utc))
215        }
216    }
217
218    impl ser::Serialize for DateTime {
219        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
220        where
221            S: ser::Serializer,
222        {
223            let mut s = serializer.serialize_struct("e7ee19d3-64cb-4286-8762-6dd8ab78eb89", 1)?;
224            s.serialize_field("d", &self.d)?;
225            s.end()
226        }
227    }
228}