diff --git a/src/parsing/.strings.rs.swp b/src/.main.rs.swp similarity index 77% rename from src/parsing/.strings.rs.swp rename to src/.main.rs.swp index 9b28f4e..049d79c 100644 Binary files a/src/parsing/.strings.rs.swp and b/src/.main.rs.swp differ diff --git a/src/main.rs b/src/main.rs index 45cf579..3260184 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,6 @@ use std:: use log:: { info, - trace, warn, debug, }; @@ -20,34 +19,67 @@ mod api; #[tokio::main] async fn main() { + // For debugging env_logger::init(); + // Tx and Rx allow you to pass data between threads let (tx,rx) = mpsc::channel(); + // Initialise the data strcut that will be sent out during API GET requests let data_to_send = Arc::new(Mutex::new(api::DataToSend { - action_type: "initialise".to_string(), + action_type: "begin".to_string(), content: "".to_string(), character: "".to_string(), })); - let data = Arc::clone(&data_to_send); + + // setup the api stuff // + + // Make clones of the data Arc for the two processes + let data_clone1 = Arc::clone(&data_to_send); let tx_clone = tx.clone(); - // Spawn a thread for warp + // Spawn a thread for warp api server tokio::spawn( async move { - api::api_process(data, tx_clone).await; + api::api_process(data_clone1, tx_clone).await; }); - debug!("and continue"); + + + // setup the parsing stuff // + // Setup the characters hashmap which will store each character in it as a Character struct let mut characters = HashMap::::new(); - let file_contents: String = fs::read_to_string("stories/story.ha").unwrap(); - // Split the file contents into tokens + + // Read the file and split it into tokens + let file_contents: String = fs::read_to_string("stories/story.ha") // TODO make this a command line argument + .unwrap_or_else(|err| + { + eprintln!("Failed to read file: {}", err); + std::process::exit(2); + }); let tokens: Vec<&str> = file_contents .split_whitespace() .collect(); + + let data_clone2 = Arc::clone(&data_to_send); // Run the parsing process - let data_clone = Arc::clone(&data_to_send); - match parsing::token_parse(&tokens, &mut characters, data_clone, &rx).await + match parsing::token_parse(&tokens, &mut characters, data_clone2, &rx).await { - Ok(()) => info!("Program exited successfully"), - Err(error) => eprintln!("{}", error), + // Exit with error or success + Ok(()) => + { + info!("Program exited successfully"); + let mut data = data_to_send.lock().unwrap(); + data.action_type = String::from("end"); + data.content = String::new(); + data.character = String::new(); + // Manually unlock the mutex + std::mem::drop(data); + let _ = rx.recv(); // Wait for the client to respond + std::process::exit(0); + }, + Err(error) => + { + eprintln!("{}", error); + std::process::exit(1); + }, } } diff --git a/src/parsing.rs b/src/parsing.rs index 6aabbe6..8c8f3a8 100644 --- a/src/parsing.rs +++ b/src/parsing.rs @@ -1,6 +1,4 @@ use std::collections::HashMap; -use std::time::Duration; -use std::thread; mod strings; use crate:: { @@ -32,9 +30,8 @@ pub async fn token_parse( loop { // If the client hasn't responded then continue (after a short pause) - if rx.try_recv().is_err() + if rx.recv().is_err() { - thread::sleep(Duration::from_millis(300)); continue } // Get the next token @@ -52,17 +49,19 @@ pub async fn token_parse( let new_character = character::Character::new(character_name.clone()); characters.insert(character_name.clone(),new_character); } - println!("Doing something with a character: {}", character_name); + info!("Doing something with a character: {}", character_name); // The index is incremented to after the character's instructions index += match character_parse(index+1, &tokens, character_name, &mut characters, &data_to_send, &rx).await { Ok(increment) => increment, Err(error) => return Err(error), - } + }; + continue } // Miscelleneous instructions if token.to_lowercase() == "end" { + info!("END command, exiting"); return Ok(()) // quit } index += 1; @@ -80,35 +79,35 @@ async fn character_parse ) -> Result { let mut sum_index: usize = index; - loop + // Ensure the index is valid (the index is not beyond the vector) + let token = tokens + .get(sum_index) + .ok_or_else(|| "File reached termination point".to_string())?; + match token.to_lowercase().as_str() { - // Ensure the index is valid (the index is not beyond the vector) - let token = tokens - .get(sum_index) - .ok_or_else(|| "File reached termination point".to_string())?; - match token.to_lowercase().as_str() + // The character is saying something, so grab the text and pass it + // to the client + "says" => { - // The character is saying something, so grab the text and pass it - // to the client - "says" => + info!("SAYS command with character {}", character_name); + match strings::extract_quoted(&tokens[sum_index+1..]) // TODO increment to after the string { - match strings::extract_quoted(&tokens[sum_index+1..]) // TODO increment to after the string + Some((output_string, counter)) => { - Some(output_string) => - { - debug!("{}", output_string); - let mut data = data_to_send.lock().unwrap(); - data.action_type = String::from("output"); - data.content = output_string; - data.character = character_name.clone(); - }, - None => return Err(String::from("Unable to read string")), - } - }, - // Catch all condition, if the instruction is unrecognised as a - // character command - _ => return Err(String::from(format!("Invalid command: {}", token))), - } - sum_index += 1; + debug!("{}", output_string); + sum_index += counter; + let mut data = data_to_send.lock().unwrap(); + data.action_type = String::from("output"); + data.content = output_string; + data.character = character_name.clone(); + }, + None => return Err(String::from("Unable to read string")), + } + }, + // Catch all condition, if the instruction is unrecognised as a + // character command + _ => return Err(String::from(format!("Invalid command: {}", token))), } + sum_index += 1; + Ok(sum_index) } diff --git a/src/parsing/strings.rs b/src/parsing/strings.rs index 67b643b..c6b1053 100644 --- a/src/parsing/strings.rs +++ b/src/parsing/strings.rs @@ -1,8 +1,11 @@ -pub fn extract_quoted(parts: &[&str]) -> Option { // TODO also return a number to increment by +pub fn extract_quoted(parts: &[&str]) -> Option<(String, usize)> { let mut vec_string = Vec::new(); + let mut counter: usize = 0; for part in parts { - if part.chars().next_back().unwrap() == '"' + counter += 1; + // End of the string + if part.chars().next_back().unwrap() == '"' // TODO allow for backslashes and ' { vec_string.push(*part); let final_string: String = vec_string.join(" "); @@ -13,8 +16,9 @@ pub fn extract_quoted(parts: &[&str]) -> Option { // TODO also return a final_string.chars() .count() - 2) .collect(); - return Some(final_string); + return Some((final_string, counter)); } + // Otherwise just add this to the list else { vec_string.push(*part); diff --git a/stories/story.ha b/stories/story.ha index d9f5a16..5ce98b6 100644 --- a/stories/story.ha +++ b/stories/story.ha @@ -1 +1,2 @@ -@tim says "hello to all the world" +@tim says "hello world, it's a good day" +END