use std::borrow::Cow;
use std::fmt;
use std::fmt::Debug;
use std::ops::Deref;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
pub type MethodId = Cow<'static, str>;
#[derive(Serialize, Debug, PartialEq)]
pub struct MethodCall {
pub id: CallId,
pub method: MethodId,
#[serde(rename = "sessionId", skip_serializing_if = "Option::is_none")]
pub session_id: Option<String>,
pub params: serde_json::Value,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct CallId(usize);
impl fmt::Display for CallId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "CallId({})", self.0)
}
}
impl CallId {
pub fn new(id: usize) -> Self {
CallId(id)
}
}
pub trait Command: serde::ser::Serialize + Method {
type Response: serde::de::DeserializeOwned + fmt::Debug;
fn response_from_value(response: serde_json::Value) -> serde_json::Result<Self::Response> {
serde_json::from_value(response)
}
}
pub struct CommandResponse<T>
where
T: fmt::Debug,
{
pub id: CallId,
pub result: T,
pub method: MethodId,
}
pub type CommandResult<T> = Result<CommandResponse<T>, Error>;
impl<T: fmt::Debug> Deref for CommandResponse<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.result
}
}
#[derive(Deserialize, Debug, PartialEq, Clone)]
pub struct CdpJsonEventMessage {
pub method: MethodId,
pub session_id: Option<String>,
pub params: serde_json::Value,
}
impl Method for CdpJsonEventMessage {
fn identifier(&self) -> MethodId {
self.method.clone()
}
}
impl EventMessage for CdpJsonEventMessage {
fn session_id(&self) -> Option<&str> {
self.params.get("sessionId").and_then(|x| x.as_str())
}
}
pub trait EventMessage: Method + DeserializeOwned + Debug {
fn session_id(&self) -> Option<&str>;
}
pub trait Method {
fn identifier(&self) -> MethodId;
fn domain_name(&self) -> MethodId {
self.split().0
}
fn method_name(&self) -> MethodId {
self.split().1
}
fn split(&self) -> (MethodId, MethodId) {
match self.identifier() {
Cow::Borrowed(id) => {
let mut iter = id.split('.');
(iter.next().unwrap().into(), iter.next().unwrap().into())
}
Cow::Owned(id) => {
let mut iter = id.split('.');
(
Cow::Owned(iter.next().unwrap().into()),
Cow::Owned(iter.next().unwrap().into()),
)
}
}
}
}
pub trait MethodType {
fn method_id() -> MethodId
where
Self: Sized;
}
#[derive(Deserialize, Debug, PartialEq, Clone)]
pub struct Request {
pub method: MethodId,
#[serde(rename = "sessionId", skip_serializing_if = "Option::is_none")]
pub session_id: Option<String>,
pub params: serde_json::Value,
}
impl Request {
pub fn new(method: MethodId, params: serde_json::Value) -> Self {
Self {
method,
params,
session_id: None,
}
}
pub fn with_session(
method: MethodId,
params: serde_json::Value,
session_id: impl Into<String>,
) -> Self {
Self {
method,
params,
session_id: Some(session_id.into()),
}
}
}
#[derive(Deserialize, Debug, PartialEq, Clone)]
pub struct Response {
pub id: CallId,
pub result: Option<serde_json::Value>,
pub error: Option<Error>,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(untagged)]
#[allow(clippy::large_enum_variant)]
pub enum Message<T = CdpJsonEventMessage> {
Response(Response),
Event(T),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ResponseError {
pub id: CallId,
pub code: usize,
pub message: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Error {
pub code: i64,
pub message: String,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Error {}: {}", self.code, self.message)
}
}
impl std::error::Error for Error {}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Binary(String);
impl AsRef<str> for Binary {
fn as_ref(&self) -> &str {
self.0.as_str()
}
}
impl AsRef<[u8]> for Binary {
fn as_ref(&self) -> &[u8] {
self.0.as_bytes()
}
}
impl From<Binary> for String {
fn from(b: Binary) -> String {
b.0
}
}
impl From<String> for Binary {
fn from(expr: String) -> Self {
Self(expr)
}
}