1use std::marker::PhantomData;
4
5use crafty_core::{Command, Query, StateMachine};
6
7use crate::error::ClientError;
8use crate::remote::{Client, KeyedClient};
9
10pub struct TypedClient<C, M> {
19 inner: C,
20 _marker: PhantomData<fn() -> M>,
21}
22
23impl<C, M> TypedClient<C, M> {
24 pub fn new(inner: C) -> Self {
26 Self {
27 inner,
28 _marker: PhantomData,
29 }
30 }
31
32 pub fn inner(&self) -> &C {
34 &self.inner
35 }
36
37 pub fn into_inner(self) -> C {
39 self.inner
40 }
41}
42
43impl<C: Client, M: StateMachine> TypedClient<C, M> {
44 pub async fn propose(&self, command: &M::Command) -> Result<M::Response, ClientError> {
50 let payload = Command::to_bytes(command).map_err(|e| ClientError::Codec(e.to_string()))?;
51 let bytes = self.inner.propose(payload).await?;
52 crafty_proto::decode(&bytes).map_err(|e| ClientError::Codec(e.to_string()))
53 }
54
55 pub async fn query(&self, query: &M::Query) -> Result<M::Response, ClientError> {
61 let payload = Query::to_bytes(query).map_err(|e| ClientError::Codec(e.to_string()))?;
62 let bytes = self.inner.query(payload).await?;
63 crafty_proto::decode(&bytes).map_err(|e| ClientError::Codec(e.to_string()))
64 }
65}
66
67impl<C: KeyedClient, M: StateMachine> TypedClient<C, M> {
68 pub async fn propose_keyed(
74 &self,
75 key: &[u8],
76 command: &M::Command,
77 ) -> Result<M::Response, ClientError> {
78 let payload = Command::to_bytes(command).map_err(|e| ClientError::Codec(e.to_string()))?;
79 let bytes = self.inner.propose_keyed(key.to_vec(), payload).await?;
80 crafty_proto::decode(&bytes).map_err(|e| ClientError::Codec(e.to_string()))
81 }
82
83 pub async fn query_keyed(
89 &self,
90 key: &[u8],
91 query: &M::Query,
92 ) -> Result<M::Response, ClientError> {
93 let payload = Query::to_bytes(query).map_err(|e| ClientError::Codec(e.to_string()))?;
94 let bytes = self.inner.query_keyed(key.to_vec(), payload).await?;
95 crafty_proto::decode(&bytes).map_err(|e| ClientError::Codec(e.to_string()))
96 }
97}