use std::marker::PhantomData;
use crafty_core::{Command, Query, StateMachine};
use crate::error::ClientError;
use crate::remote::{Client, KeyedClient};
pub struct TypedClient<C, M> {
inner: C,
_marker: PhantomData<fn() -> M>,
}
impl<C, M> TypedClient<C, M> {
pub fn new(inner: C) -> Self {
Self {
inner,
_marker: PhantomData,
}
}
pub fn inner(&self) -> &C {
&self.inner
}
pub fn into_inner(self) -> C {
self.inner
}
}
impl<C: Client, M: StateMachine> TypedClient<C, M> {
pub async fn propose(&self, command: &M::Command) -> Result<M::Response, ClientError> {
let payload = Command::to_bytes(command).map_err(|e| ClientError::Codec(e.to_string()))?;
let bytes = self.inner.propose(payload).await?;
crafty_proto::decode(&bytes).map_err(|e| ClientError::Codec(e.to_string()))
}
pub async fn query(&self, query: &M::Query) -> Result<M::Response, ClientError> {
let payload = Query::to_bytes(query).map_err(|e| ClientError::Codec(e.to_string()))?;
let bytes = self.inner.query(payload).await?;
crafty_proto::decode(&bytes).map_err(|e| ClientError::Codec(e.to_string()))
}
}
impl<C: KeyedClient, M: StateMachine> TypedClient<C, M> {
pub async fn propose_keyed(
&self,
key: &[u8],
command: &M::Command,
) -> Result<M::Response, ClientError> {
let payload = Command::to_bytes(command).map_err(|e| ClientError::Codec(e.to_string()))?;
let bytes = self.inner.propose_keyed(key.to_vec(), payload).await?;
crafty_proto::decode(&bytes).map_err(|e| ClientError::Codec(e.to_string()))
}
pub async fn query_keyed(
&self,
key: &[u8],
query: &M::Query,
) -> Result<M::Response, ClientError> {
let payload = Query::to_bytes(query).map_err(|e| ClientError::Codec(e.to_string()))?;
let bytes = self.inner.query_keyed(key.to_vec(), payload).await?;
crafty_proto::decode(&bytes).map_err(|e| ClientError::Codec(e.to_string()))
}
}