From 4c0f5713177c80c95b5aa904b1850ce7fddb335e Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Wed, 12 Oct 2022 12:48:23 -0500 Subject: [PATCH] Run rustfmt --- src/client.rs | 194 ++++++++++++++++--------------- src/code_generator.rs | 81 +++++++------ src/lib.rs | 66 +++++------ src/main.rs | 19 ++- src/message.rs | 261 +++++++++++++++++++++--------------------- 5 files changed, 303 insertions(+), 318 deletions(-) diff --git a/src/client.rs b/src/client.rs index 869d816..18b476e 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,98 +1,96 @@ -use std::sync::Arc; - -use tokio::sync::Mutex; -use futures::{ - select, - FutureExt, -}; - - -use hexland_server::{ - GlobalState, - Channel, - channel_pair, - GameController, - message::{Message, MessageWebSocket}, - msg, -}; - - -pub struct Client { - global_state: Arc, - ws: MessageWebSocket, - channel: Option, -} - -impl Client { - pub fn new(ws: MessageWebSocket, global_state: Arc) -> Self { - Client { - global_state, - ws, - channel: None - } - } - pub async fn run(&mut self) { - loop { - match &mut self.channel { - Some(channel) => { - select! { - msg = channel.rx.recv().fuse() => - self.handle_server_msg(msg.unwrap()).await, - msg = self.ws.next().fuse() => - self.handle_client_msg(msg.unwrap()).await, - }; - } - None => { - let msg = self.ws.next().await; - self.handle_client_msg(msg.unwrap()).await; - } - } - } - } - async fn handle_client_msg(&mut self, msg: Message) { - match msg.command.as_str() { - "HOST" => { - let room_code = self.global_state.code_generator.lock().await.generate(); - let mut game_controller = GameController::default(); - - let (client_channel, server_channel) = channel_pair(); - self.channel = Some(client_channel); - game_controller.channels.push(server_channel); - - let game_controller = Arc::new(Mutex::new(game_controller)); - self.global_state.rooms.lock().await.insert(room_code.clone(), Arc::clone(&game_controller)); - tokio::spawn(async move {game_loop(game_controller)}); - self.ws.send(msg!(ROOM_CODE, room_code)).await.unwrap(); - } - "JOIN" => { - let room_code = &msg.args[0]; - let rooms = self.global_state.rooms.lock().await; - let room = rooms.get(room_code); - - match room { - Some(room) => { - let mut room = room.lock().await; - let (client_channel, server_channel) = channel_pair(); - self.channel = Some(client_channel); - room.channels.push(server_channel); - self.ws.send(msg!(JOIN_OK)).await.unwrap(); - } - None => { - self.ws.send(msg!(JOIN_INVALID)).await.unwrap(); - } - } - } - _ => if let Some(channel) = &self.channel { - // Forward message to the server - channel.tx.send(msg).await.unwrap(); - } - } - } - async fn handle_server_msg(&mut self, _msg: Message) { - todo!(); - } -} - -fn game_loop(_gc: Arc>) { - todo!(); -} +use std::sync::Arc; + +use futures::{select, FutureExt}; +use tokio::sync::Mutex; + +use hexland_server::{ + channel_pair, + message::{Message, MessageWebSocket}, + msg, Channel, GameController, GlobalState, +}; + +pub struct Client { + global_state: Arc, + ws: MessageWebSocket, + channel: Option, +} + +impl Client { + pub fn new(ws: MessageWebSocket, global_state: Arc) -> Self { + Client { + global_state, + ws, + channel: None, + } + } + pub async fn run(&mut self) { + loop { + match &mut self.channel { + Some(channel) => { + select! { + msg = channel.rx.recv().fuse() => + self.handle_server_msg(msg.unwrap()).await, + msg = self.ws.next().fuse() => + self.handle_client_msg(msg.unwrap()).await, + }; + } + None => { + let msg = self.ws.next().await; + self.handle_client_msg(msg.unwrap()).await; + } + } + } + } + async fn handle_client_msg(&mut self, msg: Message) { + match msg.command.as_str() { + "HOST" => { + let room_code = self.global_state.code_generator.lock().await.generate(); + let mut game_controller = GameController::default(); + + let (client_channel, server_channel) = channel_pair(); + self.channel = Some(client_channel); + game_controller.channels.push(server_channel); + + let game_controller = Arc::new(Mutex::new(game_controller)); + self.global_state + .rooms + .lock() + .await + .insert(room_code.clone(), Arc::clone(&game_controller)); + tokio::spawn(async move { game_loop(game_controller) }); + self.ws.send(msg!(ROOM_CODE, room_code)).await.unwrap(); + } + "JOIN" => { + let room_code = &msg.args[0]; + let rooms = self.global_state.rooms.lock().await; + let room = rooms.get(room_code); + + match room { + Some(room) => { + let mut room = room.lock().await; + let (client_channel, server_channel) = channel_pair(); + self.channel = Some(client_channel); + room.channels.push(server_channel); + self.ws.send(msg!(JOIN_OK)).await.unwrap(); + } + None => { + self.ws.send(msg!(JOIN_INVALID)).await.unwrap(); + } + } + } + _ => { + if let Some(channel) = &self.channel { + // Forward message to the server + channel.tx.send(msg).await.unwrap(); + } + } + } + } + async fn handle_server_msg(&mut self, _msg: Message) { + todo!(); + } +} + +fn game_loop(_gc: Arc>) { + todo!(); +} diff --git a/src/code_generator.rs b/src/code_generator.rs index 1d6c8b5..4d6bd07 100644 --- a/src/code_generator.rs +++ b/src/code_generator.rs @@ -1,42 +1,39 @@ -use rand::RngCore; -use sha2::{Sha256, Digest}; - -pub struct CodeGenerator { - counter: u64, - salt: [u8; 32], -} - -impl CodeGenerator { - pub fn generate(&mut self) -> String { - let count = self.counter; - self.counter += 1; - - let mut hasher = Sha256::new(); - hasher.update(self.salt); - hasher.update(count.to_be_bytes()); - - format!("{:x}", hasher.finalize())[..6].to_string() - } -} - -impl Default for CodeGenerator { - fn default() -> Self { - let mut salt = [0; 32]; - rand::thread_rng().fill_bytes(&mut salt); - - CodeGenerator { - counter: 0, - salt, - } - } -} - -#[cfg(test)] -mod test { - use super::*; - #[test] - fn test_generate() { - let code = CodeGenerator::default().generate(); - assert_eq!(code.len(), 6); - } -} +use rand::RngCore; +use sha2::{Digest, Sha256}; + +pub struct CodeGenerator { + counter: u64, + salt: [u8; 32], +} + +impl CodeGenerator { + pub fn generate(&mut self) -> String { + let count = self.counter; + self.counter += 1; + + let mut hasher = Sha256::new(); + hasher.update(self.salt); + hasher.update(count.to_be_bytes()); + + format!("{:x}", hasher.finalize())[..6].to_string() + } +} + +impl Default for CodeGenerator { + fn default() -> Self { + let mut salt = [0; 32]; + rand::thread_rng().fill_bytes(&mut salt); + + CodeGenerator { counter: 0, salt } + } +} + +#[cfg(test)] +mod test { + use super::*; + #[test] + fn test_generate() { + let code = CodeGenerator::default().generate(); + assert_eq!(code.len(), 6); + } +} diff --git a/src/lib.rs b/src/lib.rs index 1a853b4..05a2b79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,36 +1,30 @@ -use std::{ - collections::HashMap, - sync::Arc, -}; - -use tokio::sync::{Mutex, mpsc}; - -pub mod message; -use message::{Message}; -mod code_generator; -use code_generator::CodeGenerator; - -#[derive(Default)] -pub struct GlobalState { - pub code_generator: Arc>, - pub rooms: Arc>>>>, -} - -pub struct Channel { - pub tx: mpsc::Sender, - pub rx: mpsc::Receiver, -} - -pub fn channel_pair() -> (Channel, Channel) { - let (atx, brx) = mpsc::channel(32); - let (btx, arx) = mpsc::channel(32); - ( - Channel { tx: atx, rx: arx }, - Channel { tx: btx, rx: brx }, - ) -} - -#[derive(Default)] -pub struct GameController { - pub channels: Vec, -} +use std::{collections::HashMap, sync::Arc}; + +use tokio::sync::{mpsc, Mutex}; + +pub mod message; +use message::Message; +mod code_generator; +use code_generator::CodeGenerator; + +#[derive(Default)] +pub struct GlobalState { + pub code_generator: Arc>, + pub rooms: Arc>>>>, +} + +pub struct Channel { + pub tx: mpsc::Sender, + pub rx: mpsc::Receiver, +} + +pub fn channel_pair() -> (Channel, Channel) { + let (atx, brx) = mpsc::channel(32); + let (btx, arx) = mpsc::channel(32); + (Channel { tx: atx, rx: arx }, Channel { tx: btx, rx: brx }) +} + +#[derive(Default)] +pub struct GameController { + pub channels: Vec, +} diff --git a/src/main.rs b/src/main.rs index ec71bd7..977708c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,9 @@ -use std::{ - sync::Arc, - io::Error as IoError, -}; +use std::{io::Error as IoError, sync::Arc}; -use tokio::{ - net::{TcpListener}, -}; +use tokio::net::TcpListener; -use hexland_server::GlobalState; use hexland_server::message::MessageWebSocket; +use hexland_server::GlobalState; mod client; use client::Client; @@ -27,9 +22,11 @@ async fn main() -> Result<(), IoError> { let global_state = Arc::clone(&global_state); tokio::spawn(async move { // Upgrade to a WS connection - let ws = MessageWebSocket(tokio_tungstenite::accept_async(stream) - .await - .expect("Could not establish connection")); + let ws = MessageWebSocket( + tokio_tungstenite::accept_async(stream) + .await + .expect("Could not establish connection"), + ); println!("Connected to {}", addr); Client::new(ws, global_state).run().await; }); diff --git a/src/message.rs b/src/message.rs index 5824baf..b75b1c9 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,131 +1,130 @@ -use std::convert::{From, TryFrom}; - -use tokio::net::TcpStream; -use tokio_tungstenite::{ - WebSocketStream, - tungstenite::Message as WsMessage, -}; -use futures::{StreamExt, SinkExt}; -use lazy_static::lazy_static; - -#[derive(PartialEq, Debug)] -pub struct Message { - pub command: String, - pub args: Vec, -} - -pub type Result = std::result::Result; - -#[repr(u8)] -#[derive(PartialEq, Debug)] -pub enum Error { - BadParse, - NonText, - Unknown, -} - -impl Message { - pub fn parse(text: String) -> Result { - lazy_static! { - static ref RE: regex::Regex = regex::Regex::new(r"^([A-Z_]+):\s*(.*)").unwrap(); - } - match RE.captures(text.as_str()) { - Some(captures) => { - if captures.len() < 3 { - Err(Error::BadParse) - } else { - let command = captures.get(1).unwrap().as_str().to_string(); - let args = captures.get(2).unwrap().as_str() - .split(',') - .map(|s| s.trim().to_string()) - .collect(); - Ok(Message { command, args }) - } - } - None => Err(Error::BadParse), - } - } -} - -impl TryFrom for Message { - type Error = Error; - - fn try_from(ws_message: WsMessage) -> Result { - let text = match ws_message { - WsMessage::Text(text) => text, - _ => return Err(Error::NonText) - }; - Message::parse(text) - } -} - -impl From for WsMessage { - fn from(message: Message) -> Self { - WsMessage::Text(message.to_string()) - } -} - -pub struct MessageWebSocket(pub WebSocketStream); - -impl MessageWebSocket { - pub async fn next(&mut self) -> Result { - if let Some(Ok(msg)) = self.0.next().await { - msg.try_into() - } else { - Err(Error::Unknown) - } - } - pub async fn send(&mut self, msg: Message) -> Result<()> { - if self.0.send(msg.into()).await.is_err() { - Err(Error::Unknown) - } else { - Ok(()) - } - } -} - -#[macro_export] -macro_rules! msg { - ( $command:ident) => { - { - let command = stringify!($command).to_string(); - let args = vec![]; - Message { command, args } - } - }; - ( $command:ident, $( $arg:expr ),*) => { - { - let command = stringify!($command).to_string(); - let args = vec![$($arg.to_string()),*]; - Message { command, args } - } - }; -} - - -impl std::fmt::Display for Message { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { - if self.args.is_empty() { - write!(f, "{}:", self.command) - } else { - write!(f, "{}: {}", self.command, self.args.as_slice().join(", ")) - } - } -} - -#[cfg(test)] -mod test { - use super::*; - #[test] - fn test_parse() -> Result<()> { - let text = "COMMAND: arg1, arg2"; - let msg = Message::parse(text.to_string())?; - assert_eq!(msg!(COMMAND, "arg1", "arg2"), msg); - Ok(()) - } - #[test] - fn test_to_string() { - let msg = msg!(COMMAND, "arg1", "arg2"); - assert_eq!(msg.to_string(), "COMMAND: arg1, arg2".to_string()); - } -} +use std::convert::{From, TryFrom}; + +use futures::{SinkExt, StreamExt}; +use lazy_static::lazy_static; +use tokio::net::TcpStream; +use tokio_tungstenite::{tungstenite::Message as WsMessage, WebSocketStream}; + +#[derive(PartialEq, Debug)] +pub struct Message { + pub command: String, + pub args: Vec, +} + +pub type Result = std::result::Result; + +#[repr(u8)] +#[derive(PartialEq, Debug)] +pub enum Error { + BadParse, + NonText, + Unknown, +} + +impl Message { + pub fn parse(text: String) -> Result { + lazy_static! { + static ref RE: regex::Regex = regex::Regex::new(r"^([A-Z_]+):\s*(.*)").unwrap(); + } + match RE.captures(text.as_str()) { + Some(captures) => { + if captures.len() < 3 { + Err(Error::BadParse) + } else { + let command = captures.get(1).unwrap().as_str().to_string(); + let args = captures + .get(2) + .unwrap() + .as_str() + .split(',') + .map(|s| s.trim().to_string()) + .collect(); + Ok(Message { command, args }) + } + } + None => Err(Error::BadParse), + } + } +} + +impl TryFrom for Message { + type Error = Error; + + fn try_from(ws_message: WsMessage) -> Result { + let text = match ws_message { + WsMessage::Text(text) => text, + _ => return Err(Error::NonText), + }; + Message::parse(text) + } +} + +impl From for WsMessage { + fn from(message: Message) -> Self { + WsMessage::Text(message.to_string()) + } +} + +pub struct MessageWebSocket(pub WebSocketStream); + +impl MessageWebSocket { + pub async fn next(&mut self) -> Result { + if let Some(Ok(msg)) = self.0.next().await { + msg.try_into() + } else { + Err(Error::Unknown) + } + } + pub async fn send(&mut self, msg: Message) -> Result<()> { + if self.0.send(msg.into()).await.is_err() { + Err(Error::Unknown) + } else { + Ok(()) + } + } +} + +#[macro_export] +macro_rules! msg { + ( $command:ident) => { + { + let command = stringify!($command).to_string(); + let args = vec![]; + Message { command, args } + } + }; + ( $command:ident, $( $arg:expr ),*) => { + { + let command = stringify!($command).to_string(); + let args = vec![$($arg.to_string()),*]; + Message { command, args } + } + }; +} + +impl std::fmt::Display for Message { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { + if self.args.is_empty() { + write!(f, "{}:", self.command) + } else { + write!(f, "{}: {}", self.command, self.args.as_slice().join(", ")) + } + } +} + +#[cfg(test)] +mod test { + use super::*; + #[test] + fn test_parse() -> Result<()> { + let text = "COMMAND: arg1, arg2"; + let msg = Message::parse(text.to_string())?; + assert_eq!(msg!(COMMAND, "arg1", "arg2"), msg); + Ok(()) + } + #[test] + fn test_to_string() { + let msg = msg!(COMMAND, "arg1", "arg2"); + assert_eq!(msg.to_string(), "COMMAND: arg1, arg2".to_string()); + } +}