diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 10 | ||||
| -rw-r--r-- | src/play.rs | 67 |
2 files changed, 69 insertions, 8 deletions
diff --git a/src/main.rs b/src/main.rs index 32e5d58..b157b71 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ +mod play; mod session; mod template; +use crate::play::handle_play; use crate::session::{HandObject, Session}; use crate::template::{IndexTemplate, SessionTemplate}; use askama::Template; -use axum::extract::ws::WebSocket; use axum::extract::{Path, Query, State, WebSocketUpgrade}; use axum::http::{StatusCode, header}; use axum::response::{Html, IntoResponse, Response}; @@ -145,10 +146,3 @@ async fn update_hands( async fn upgrade_play(ws: WebSocketUpgrade, State(state): State<Arc<AppState>>) -> Response { ws.on_upgrade(|socket| handle_play(socket, state)) } - -#[allow(unused_variables)] -async fn handle_play(mut socket: WebSocket, state: Arc<AppState>) { - while let Some(msg) = socket.recv().await { - todo!() - } -} diff --git a/src/play.rs b/src/play.rs new file mode 100644 index 0000000..e88ae7e --- /dev/null +++ b/src/play.rs @@ -0,0 +1,67 @@ +use crate::AppState; +use axum::extract::ws::{Message, Utf8Bytes, WebSocket}; +use serde::{Deserialize, Serialize}; +use std::error::Error; +use std::sync::Arc; + +#[derive(Deserialize)] +enum IncomingPlayMessage { + Initialize { id: String }, +} + +#[derive(Serialize)] +enum OutgoingPlayMessage<'a> { + Initialize { colors: Vec<&'a String> }, +} + +struct PlayState { + id: Option<String>, +} + +pub async fn handle_play(mut socket: WebSocket, app_state: Arc<AppState>) { + let mut play_state = PlayState { id: None }; + + while let Some(msg) = socket.recv().await { + let mut process = async |msg: Result<Message, axum::Error>| -> Result<(), Box<dyn Error>> { + let msg: IncomingPlayMessage = serde_json::from_str(msg?.to_text()?)?; + match msg { + IncomingPlayMessage::Initialize { id } => { + // Blocked so that the mutex guard is dropped after cloning the color names, + // preventing a potential deadlock when using .await after sending something + // through the socket, which would be possible if using tokio::sync::Mutex. + // Of course, the sessions Mutex is std::sync::Mutex instead, which does not + // allow locking the mutex through .await anyway. + let colors: Vec<String> = { + let sessions = app_state.sessions.lock().unwrap(); + // TODO: Non-string Error might be useful + let session = sessions.get(&id).ok_or("Session did not exist")?; + + session.hands.keys().cloned().collect() + }; + + play_state.id = Some(id); + + let response = OutgoingPlayMessage::Initialize { + colors: colors.iter().collect(), + }; + socket + .send(Message::Text(Utf8Bytes::from(serde_json::to_string( + &response, + )?))) + .await?; + } + } + Ok(()) + }; + + if let Ok(Message::Text(_)) = msg + && let Err(err) = process(msg).await + { + eprintln!( + "Encountered an error while handling a message from a player: {}", + err + ); + break; + } + } +} |
