Created
July 5, 2019 20:26
-
-
Save andreastt/f2bf8e5f5fc4adad73670c36cf7203f6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![allow(dead_code)] | |
#![allow(unused_imports)] | |
use serde::de::{self, SeqAccess, Visitor}; | |
use serde::{Deserialize, Deserializer, Serialize, Serializer}; | |
use serde_json::{json, Map, Value}; | |
use std::borrow::Cow; | |
use std::fmt; | |
use std::marker::PhantomData; | |
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | |
enum Selector { | |
#[serde(rename = "css selector")] | |
CSS, | |
XPath, | |
} | |
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | |
struct Locator { | |
using: Selector, | |
value: String, | |
} | |
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | |
enum WebDriverCommand { | |
#[serde(rename = "WebDriver:FindElement")] | |
FindElement(Locator), | |
#[serde(rename = "WebDriver:GetTimeouts")] | |
GetTimeouts, | |
} | |
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | |
#[serde(untagged)] | |
enum Command { | |
WebDriver(WebDriverCommand), | |
} | |
impl Command { | |
pub fn name(&self) -> String { | |
let (command_name, _) = self.first_entry(); | |
command_name | |
} | |
pub fn params(&self) -> Value { | |
let (_, params) = self.first_entry(); | |
params | |
} | |
fn first_entry(&self) -> (String, serde_json::Value) { | |
let val = serde_json::to_value(&self).unwrap(); | |
let items = val.as_object().unwrap(); | |
let mut iter = items.iter(); | |
let (command, params) = iter.next().unwrap(); | |
(command.to_string(), params.clone()) | |
} | |
} | |
type MessageId = i32; | |
#[derive(Debug, Clone, PartialEq, Deserialize)] | |
struct Request(MessageId, Command); | |
impl Request { | |
pub fn id(&self) -> MessageId { | |
self.0 | |
} | |
pub fn command(&self) -> &Command { | |
&self.1 | |
} | |
pub fn params(&self) -> Value { | |
self.command().params() | |
} | |
} | |
impl Serialize for Request { | |
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | |
where | |
S: Serializer, | |
{ | |
( | |
0, | |
self.id(), | |
self.command().name(), | |
self.params(), | |
) | |
.serialize(serializer) | |
} | |
} | |
#[derive(Debug, Clone, PartialEq, Serialize)] | |
#[serde(untagged)] | |
enum Message { | |
Incoming(Request), | |
} | |
// TODO(ato): | |
// - turn the following into a SeqAccess | |
// - maybe try implement it on Request | |
// - figure out responses (result and error) | |
// (error will need a similar approach as this) | |
impl<'de> Deserialize<'de> for Message { | |
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | |
where | |
D: Deserializer<'de>, | |
{ | |
#[derive(Debug, Deserialize)] | |
struct Mapping { | |
direction: u8, | |
id: MessageId, | |
name: String, | |
params: Value, | |
}; | |
let Mapping { | |
direction, | |
id, | |
name, | |
params, | |
} = Mapping::deserialize(deserializer)?; | |
// map command name (i.e. "WebDriver:FindElement") to parameters | |
// so the serialisation can be automatically derived for Command | |
let map = { | |
let mut command_to_params = Map::new(); | |
command_to_params.insert(name, params); | |
Value::Object(command_to_params) | |
}; | |
let msg = match direction { | |
0 => { | |
let command = serde_json::from_value(map).unwrap(); | |
Message::Incoming(Request(id, command)) | |
} | |
1 => panic!("outoging"), | |
_ => panic!(), | |
}; | |
Ok(msg) | |
} | |
} | |
fn main() { | |
let locator = Locator { | |
using: Selector::CSS, | |
value: "body".into(), | |
}; | |
let find_element = WebDriverCommand::FindElement(locator); | |
let command = Command::WebDriver(find_element); | |
let request = Request(42, command); | |
let msg = Message::Incoming(request); | |
dbg!(serde_json::to_string(&msg).unwrap()); | |
dbg!(&msg); | |
let actual: Message = serde_json::from_value( | |
json!([0,42,"WebDriver:FindElement",{"using":"css selector","value":"body"}]), | |
) | |
.unwrap(); | |
assert_eq!(msg, actual); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment