scratch_cloud_server/
lib.rs1use 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}