1use std::ffi::CStr;
18use std::sync::Arc;
19
20use futures::future;
21use futures::future::BoxFuture;
22use futures::stream::BoxStream;
23use futures::FutureExt;
24
25use crate::help::Spawner;
26use crate::Framing;
27use crate::FramingDecoded;
28use crate::FramingEncodedFinal;
29use crate::Protocol;
30
31#[derive(Debug)]
32pub enum ClientStreamElement<Payload> {
33 Reply(Payload),
34 ApplicationEx(Payload),
35}
36
37impl<Payload> ClientStreamElement<Payload> {
38 pub fn payload(&self) -> &Payload {
39 match self {
40 ClientStreamElement::Reply(payload) | ClientStreamElement::ApplicationEx(payload) => {
41 payload
42 }
43 }
44 }
45
46 pub fn into_payload(self) -> Payload {
47 match self {
48 ClientStreamElement::Reply(payload) | ClientStreamElement::ApplicationEx(payload) => {
49 payload
50 }
51 }
52 }
53}
54
55pub trait ClientFactory {
56 type Api: ?Sized;
57
58 fn new<P, T>(protocol: P, transport: T) -> Arc<Self::Api>
59 where
60 P: Protocol<Frame = T> + 'static,
61 T: Transport,
62 P::Deserializer: Send,
63 {
64 let spawner = crate::NoopSpawner;
65 Self::with_spawner(protocol, transport, spawner)
66 }
67
68 fn with_spawner<P, T, S>(protocol: P, transport: T, spawner: S) -> Arc<Self::Api>
69 where
70 P: Protocol<Frame = T> + 'static,
71 T: Transport,
72 P::Deserializer: Send,
73 S: Spawner;
74}
75
76pub trait Transport: Framing + Send + Sync + Sized + 'static {
77 type RpcOptions: Default;
78
79 fn call(
80 &self,
81 service_name: &'static CStr,
82 fn_name: &'static CStr,
83 req: FramingEncodedFinal<Self>,
84 rpc_options: Self::RpcOptions,
85 ) -> BoxFuture<'static, anyhow::Result<FramingDecoded<Self>>>;
86
87 fn call_stream(
88 &self,
89 _service_name: &'static CStr,
90 _fn_name: &'static CStr,
91 _req: FramingEncodedFinal<Self>,
92 _rpc_options: Self::RpcOptions,
93 ) -> BoxFuture<
94 'static,
95 anyhow::Result<(
96 FramingDecoded<Self>,
97 BoxStream<'static, anyhow::Result<ClientStreamElement<FramingDecoded<Self>>>>,
98 )>,
99 > {
100 future::err(anyhow::Error::msg(
101 "Streaming is not supported by this transport",
102 ))
103 .boxed()
104 }
105
106 fn create_interaction(&self, _method_name: &'static CStr) -> Result<Self, anyhow::Error> {
107 anyhow::bail!("Interactions are not supported by this transport");
108 }
109}