Skip to main content

clankerdiff_client/
transport.rs

1use crate::{
2    ClientError,
3    protocol::{
4        client::{ClientCommand, DocumentCache, LocalClientTransport},
5        server::{ServerEvent, ServerMessage},
6        shared::LocalEnd,
7    },
8};
9use std::future::Future;
10
11#[cfg(feature = "websocket")]
12use crate::ConnectionHeader;
13
14#[cfg(feature = "websocket")]
15#[cfg_attr(not(target_arch = "wasm32"), path = "transport/native.rs")]
16#[cfg_attr(target_arch = "wasm32", path = "transport/web.rs")]
17mod ws;
18
19#[cfg(not(target_arch = "wasm32"))]
20pub trait MaybeSend: Send {}
21#[cfg(not(target_arch = "wasm32"))]
22impl<T: Send> MaybeSend for T {}
23#[cfg(target_arch = "wasm32")]
24pub trait MaybeSend {}
25#[cfg(target_arch = "wasm32")]
26impl<T> MaybeSend for T {}
27
28pub trait ClientMessageTransport: MaybeSend + 'static {
29    fn send(
30        &mut self,
31        command: ClientCommand,
32    ) -> impl Future<Output = Result<(), ClientError>> + MaybeSend;
33    fn recv(&mut self) -> impl Future<Output = Result<ServerMessage, ClientError>> + MaybeSend;
34    fn close(&mut self) -> impl Future<Output = ()> + MaybeSend;
35}
36
37pub(crate) trait Transport: MaybeSend + 'static {
38    fn send(
39        &mut self,
40        command: ClientCommand,
41    ) -> impl Future<Output = Result<(), ClientError>> + MaybeSend;
42    fn recv(&mut self) -> impl Future<Output = Result<ServerEvent, ClientError>> + MaybeSend;
43    fn close(&mut self) -> impl Future<Output = ()> + MaybeSend;
44
45    fn reconnects(&self) -> bool {
46        false
47    }
48
49    fn reconnect(&mut self) -> impl Future<Output = Result<(), ClientError>> + MaybeSend {
50        async { Err(ClientError::Disconnected) }
51    }
52}
53
54impl Transport for LocalClientTransport {
55    async fn send(&mut self, command: ClientCommand) -> Result<(), ClientError> {
56        LocalEnd::send(self, command)
57            .await
58            .map_err(|_| ClientError::Disconnected)
59    }
60
61    async fn recv(&mut self) -> Result<ServerEvent, ClientError> {
62        LocalEnd::recv(self)
63            .await
64            .map_err(|_| ClientError::Disconnected)
65    }
66
67    async fn close(&mut self) {
68        LocalEnd::close(self);
69    }
70}
71
72impl ClientMessageTransport for LocalEnd<ClientCommand, ServerMessage> {
73    async fn send(&mut self, command: ClientCommand) -> Result<(), ClientError> {
74        LocalEnd::send(self, command)
75            .await
76            .map_err(|_| ClientError::Disconnected)
77    }
78
79    async fn recv(&mut self) -> Result<ServerMessage, ClientError> {
80        LocalEnd::recv(self)
81            .await
82            .map_err(|_| ClientError::Disconnected)
83    }
84
85    async fn close(&mut self) {
86        LocalEnd::close(self);
87    }
88}
89
90pub(crate) struct Decoded<T> {
91    transport: T,
92    cache: DocumentCache,
93}
94
95impl<T> Decoded<T> {
96    pub(crate) fn new(transport: T) -> Self {
97        Self {
98            transport,
99            cache: DocumentCache::default(),
100        }
101    }
102}
103
104impl<T: ClientMessageTransport> Transport for Decoded<T> {
105    async fn send(&mut self, command: ClientCommand) -> Result<(), ClientError> {
106        self.transport.send(command).await
107    }
108
109    async fn recv(&mut self) -> Result<ServerEvent, ClientError> {
110        let message = self.transport.recv().await?;
111        Ok(self.cache.apply_event(message)?)
112    }
113
114    async fn close(&mut self) {
115        self.transport.close().await;
116    }
117}
118
119#[cfg(feature = "websocket")]
120pub(crate) struct Reconnecting {
121    url: String,
122    headers: Vec<ConnectionHeader>,
123    socket: Decoded<ws::WebSocketTransport>,
124}
125
126#[cfg(feature = "websocket")]
127impl Reconnecting {
128    pub(crate) async fn connect(
129        url: &str,
130        headers: Vec<ConnectionHeader>,
131    ) -> Result<Self, ClientError> {
132        let socket = ws::WebSocketTransport::try_connect(url, &headers).await?;
133        Ok(Self {
134            url: url.to_owned(),
135            headers,
136            socket: Decoded::new(socket),
137        })
138    }
139}
140
141#[cfg(feature = "websocket")]
142impl Transport for Reconnecting {
143    async fn send(&mut self, command: ClientCommand) -> Result<(), ClientError> {
144        self.socket.send(command).await
145    }
146
147    async fn recv(&mut self) -> Result<ServerEvent, ClientError> {
148        self.socket.recv().await
149    }
150
151    async fn close(&mut self) {
152        self.socket.close().await;
153    }
154
155    fn reconnects(&self) -> bool {
156        true
157    }
158
159    async fn reconnect(&mut self) -> Result<(), ClientError> {
160        let socket = ws::WebSocketTransport::try_connect(&self.url, &self.headers).await?;
161        self.socket = Decoded::new(socket);
162        Ok(())
163    }
164}