scratch_cloud_server/
lib.rs

1use futures_util::SinkExt;
2use futures_util::StreamExt;
3use tokio::net::TcpStream;
4use tokio_tungstenite::tungstenite::Message as WSMessage;
5
6pub mod messages;
7
8use messages::*;
9
10#[derive(Debug)]
11pub enum Error {
12    ExpectedTextMsg,
13    JSONError(serde_json::Error),
14    WSError(tokio_tungstenite::tungstenite::Error),
15}
16impl From<serde_json::Error> for Error {
17    fn from(value: serde_json::Error) -> Self {
18        Self::JSONError(value)
19    }
20}
21impl From<tokio_tungstenite::tungstenite::Error> for Error {
22    fn from(value: tokio_tungstenite::tungstenite::Error) -> Self {
23        Self::WSError(value)
24    }
25}
26impl std::fmt::Display for Error {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        write!(f, "{:?}", self)
29    }
30}
31impl std::error::Error for Error {}
32
33pub struct CloudServerStream {
34    write:
35        futures_util::stream::SplitSink<tokio_tungstenite::WebSocketStream<TcpStream>, WSMessage>,
36    read: futures_util::stream::SplitStream<tokio_tungstenite::WebSocketStream<TcpStream>>,
37}
38impl CloudServerStream {
39    pub async fn from_tcp_stream(stream: TcpStream) -> Result<Self, Error> {
40        let ws_stream = tokio_tungstenite::accept_async(stream).await?;
41        let (write, read) = ws_stream.split();
42
43        Ok(Self { write, read })
44    }
45
46    pub async fn recv(&mut self) -> Result<Option<ServerboundMessage>, Error> {
47        let msg = match self.read.next().await {
48            Some(msg) => match msg? {
49                WSMessage::Text(msg) => msg.to_string(),
50                WSMessage::Close(msg) => {
51                    match msg {
52                        Some(msg) => println!("Closed with frame: {}", msg),
53                        None => {}
54                    }
55                    return Ok(None);
56                }
57                _ => {
58                    return Err(Error::ExpectedTextMsg);
59                }
60            },
61            None => {
62                return Ok(None);
63            }
64        };
65        Ok(Some(serde_json::from_str(&msg)?))
66    }
67
68    pub async fn send(&mut self, msg: ClientboundMessage) -> Result<(), Error> {
69        let value = serde_json::to_string(&msg)?;
70        self.write.send(WSMessage::Text(value.into())).await?;
71        Ok(())
72    }
73}