use std::fmt::{self, Debug, Display};
use std::hash::Hash;
use serde::Serialize;
use crate::jsonrpc::{ConnectionTo, RawJsonRpcId};
use crate::role::Role;
use crate::v1::schema as v1;
#[cfg(feature = "unstable_protocol_v2")]
use crate::v2::schema as v2;
#[allow(private_bounds)]
pub trait Protocol: sealed::Sealed + Copy + Debug + Default + Send + Sync + 'static {
type RequestId: Clone
+ Debug
+ Display
+ Eq
+ Hash
+ Serialize
+ Into<RawJsonRpcId>
+ Send
+ Sync
+ 'static;
type Connection<Counterpart: Role>: Clone
+ Send
+ Sync
+ Into<ConnectionTo<Counterpart>>
+ 'static;
}
pub(crate) mod sealed {
use super::{ConnectionTo, Protocol, RawJsonRpcId, Role};
pub trait Sealed {
fn protocol_version() -> Option<crate::schema::ProtocolVersion>;
fn connection_from_raw<Counterpart: Role>(
connection: ConnectionTo<Counterpart>,
) -> <Self as Protocol>::Connection<Counterpart>
where
Self: Protocol;
fn request_id_from_raw(
id: &RawJsonRpcId,
) -> Result<<Self as Protocol>::RequestId, crate::Error>
where
Self: Protocol;
fn request_id_from_string(id: String) -> <Self as Protocol>::RequestId
where
Self: Protocol;
}
}
pub(crate) fn protocol_version<P: Protocol>() -> Option<crate::schema::ProtocolVersion> {
<P as sealed::Sealed>::protocol_version()
}
pub(crate) fn connection_from_raw<P: Protocol, Counterpart: Role>(
connection: ConnectionTo<Counterpart>,
) -> P::Connection<Counterpart> {
<P as sealed::Sealed>::connection_from_raw(connection)
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct Raw;
impl sealed::Sealed for Raw {
fn protocol_version() -> Option<crate::schema::ProtocolVersion> {
None
}
fn connection_from_raw<Counterpart: Role>(
connection: ConnectionTo<Counterpart>,
) -> ConnectionTo<Counterpart> {
connection
}
fn request_id_from_raw(id: &RawJsonRpcId) -> Result<RawJsonRpcId, crate::Error> {
Ok(id.clone())
}
fn request_id_from_string(id: String) -> RawJsonRpcId {
RawJsonRpcId::Str(id)
}
}
impl Protocol for Raw {
type RequestId = RawJsonRpcId;
type Connection<Counterpart: Role> = ConnectionTo<Counterpart>;
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct V1;
impl sealed::Sealed for V1 {
fn protocol_version() -> Option<crate::schema::ProtocolVersion> {
Some(crate::schema::ProtocolVersion::V1)
}
fn connection_from_raw<Counterpart: Role>(
connection: ConnectionTo<Counterpart>,
) -> super::v1_connection::ConnectionTo<Counterpart> {
super::v1_connection::ConnectionTo { inner: connection }
}
fn request_id_from_raw(id: &RawJsonRpcId) -> Result<v1::RequestId, crate::Error> {
Ok(id.clone().into())
}
fn request_id_from_string(id: String) -> v1::RequestId {
v1::RequestId::Str(id)
}
}
impl Protocol for V1 {
type RequestId = v1::RequestId;
type Connection<Counterpart: Role> = super::v1_connection::ConnectionTo<Counterpart>;
}
#[cfg(feature = "unstable_protocol_v2")]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct V2;
#[cfg(feature = "unstable_protocol_v2")]
impl sealed::Sealed for V2 {
fn protocol_version() -> Option<crate::schema::ProtocolVersion> {
Some(crate::schema::ProtocolVersion::V2)
}
fn connection_from_raw<Counterpart: Role>(
connection: ConnectionTo<Counterpart>,
) -> super::v2_connection::ConnectionTo<Counterpart> {
super::v2_connection::ConnectionTo { inner: connection }
}
fn request_id_from_raw(id: &RawJsonRpcId) -> Result<v2::RequestId, crate::Error> {
id.clone().try_into()
}
fn request_id_from_string(id: String) -> v2::RequestId {
v2::RequestId::Str(id)
}
}
#[cfg(feature = "unstable_protocol_v2")]
impl Protocol for V2 {
type RequestId = v2::RequestId;
type Connection<Counterpart: Role> = super::v2_connection::ConnectionTo<Counterpart>;
}
pub(crate) struct HandleId<P: Protocol> {
raw: RawJsonRpcId,
typed: P::RequestId,
}
impl<P: Protocol> HandleId<P> {
pub(crate) fn generated(id: String) -> Self {
Self {
typed: P::request_id_from_string(id.clone()),
raw: RawJsonRpcId::Str(id),
}
}
pub(crate) fn from_raw(raw: RawJsonRpcId) -> Result<Self, crate::Error> {
Ok(Self {
typed: P::request_id_from_raw(&raw)?,
raw,
})
}
pub(crate) fn raw(&self) -> &RawJsonRpcId {
&self.raw
}
pub(crate) fn typed(&self) -> &P::RequestId {
&self.typed
}
pub(crate) fn into_protocol<Q: Protocol>(self) -> Result<HandleId<Q>, crate::Error> {
HandleId::from_raw(self.raw)
}
pub(crate) fn into_raw(self) -> HandleId<Raw> {
HandleId::raw_layer(self.raw)
}
}
impl HandleId<Raw> {
pub(crate) fn raw_layer(raw: RawJsonRpcId) -> Self {
Self {
typed: raw.clone(),
raw,
}
}
}
impl<P: Protocol> Clone for HandleId<P> {
fn clone(&self) -> Self {
Self {
raw: self.raw.clone(),
typed: self.typed.clone(),
}
}
}
impl<P: Protocol> Debug for HandleId<P> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.raw, f)
}
}