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}