From 20174e697cdaa7ed165ea1f549e937cc0c6f4d17 Mon Sep 17 00:00:00 2001 From: deadvey Date: Fri, 15 May 2026 19:19:17 +0100 Subject: [PATCH] removed unwraps and added a method to Results called .unwrap_or_exit(error_message, error_code) This tries to unwrap and if it can't then it outputs the error message with the error!() macro (log library) and exits with the error code. This is to be used instead of expect and is for fatal errors --- client/main.py | 2 +- report.odt | Bin 14640 -> 15538 bytes server/src/character.rs | 6 ++--- server/src/main.rs | 35 +++++++++++++++----------- server/src/parsing.rs | 22 ++++++++++------ server/src/parsing/character_parse.rs | 7 +++--- server/src/parsing/strings.rs | 6 ++--- server/src/traits.rs | 23 +++++++++++++++++ stories/test.zip | Bin 628 -> 628 bytes 9 files changed, 69 insertions(+), 32 deletions(-) create mode 100644 server/src/traits.rs diff --git a/client/main.py b/client/main.py index eb48167..7732871 100644 --- a/client/main.py +++ b/client/main.py @@ -31,7 +31,7 @@ def choice(choices): choice = int(input()) except: choice = 0 - print("Invalid choice") + print("Invalid choice, defaulting to 0") requests.post(api_url, json=choice); # Character outputs text to the user diff --git a/report.odt b/report.odt index adf9b533cc405c9d97cfaf4b2bbd4b7af6c65056..a73a9ffab6edb50e45f9676c45f2e852535dcd23 100644 GIT binary patch delta 9304 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 delta 8399 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 diff --git a/server/src/character.rs b/server/src/character.rs index adf6883..9fc4d13 100644 --- a/server/src/character.rs +++ b/server/src/character.rs @@ -63,15 +63,15 @@ pub fn character_parse(archive: &mut ZipArchive) { // Get the JSON file to a string let mut characters_file = archive.by_name("characters.json") - .map_err (|err| format!("Unable to read story file: {err}"))?; + .map_err (|err| format!("Unable to read character file: {err}"))?; let mut file_contents = String::new(); characters_file.read_to_string(&mut file_contents) - .map_err (|err| format!("Unable to read story file to string: {err}"))?; + .map_err (|err| format!("Unable to read character file to string: {err}"))?; // Serialise this to a HashMap let characters: HashMap = serde_json::from_str(&file_contents) - .expect("JSON was not well-formatted"); + .map_err (|err| format!("Invalid JSON in characters.json: {err}"))?; debug!("{characters:?}"); Ok(Arc::new(Mutex::new(characters))) } diff --git a/server/src/main.rs b/server/src/main.rs index 55a4f08..012db22 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,3 +1,9 @@ +mod parsing; +mod character; +mod config; +mod api; +mod traits; + use std:: { process::exit, @@ -24,11 +30,10 @@ use zip:: { ZipArchive, }; - -mod parsing; -mod character; -mod config; -mod api; +use crate:: +{ + traits::UnwrapOrExit, +}; #[tokio::main] async fn main() @@ -38,23 +43,23 @@ async fn main() // Tx and Rx allow you to pass data between threads let (tx,rx) = mpsc::channel(); // Unzip zip archive to get data for story - let file_name = args().nth(1) + let file_name = args().nth(1) // Get filename from arguments .unwrap_or_else (|| { error!("No filename specified"); - exit(5); + exit(10); }); - let file = File::open(format!("../stories/{file_name}")) + let file = File::open(format!("../stories/{file_name}")) // Get the file .unwrap_or_else (|err| { error!("Failed to open file: {err}"); - exit(2); + exit(11); }); - let mut archive = ZipArchive::new(file) + let mut archive = ZipArchive::new(file) // Open the archive .unwrap_or_else (|err| { error!("Failed to open archive: {err}"); - exit(3); + exit(12); }); // Setup the characters hashmap which will store each character in it as a Character struct let characters = match character::character_parse(&mut archive) @@ -67,7 +72,7 @@ async fn main() Err(error) => { error!("{error}"); - exit(3); + exit(13); }, }; // Initialise the data strcut that will be sent out during API GET requests @@ -99,14 +104,14 @@ async fn main() .unwrap_or_else (|err| { error!("Unable to read story file: {err}"); - exit(4); + exit(14); }); let mut file_contents = String::new(); story_file.read_to_string(&mut file_contents) .unwrap_or_else (|err| { error!("Unable to read story file to string: {err}"); - exit(5); + exit(14); }); // Tokenise story file let tokens: Vec<&str> = file_contents @@ -127,7 +132,7 @@ async fn main() Ok(()) => { info!("Program exited successfully"); - let mut data = data_to_send.lock().unwrap(); // TODO eh? + let mut data = data_to_send.lock().unwrap_or_exit("Data to send Mutex was poisoned",2); // TODO test data.action_type = String::from("end"); data.content = String::new(); data.character = String::new(); diff --git a/server/src/parsing.rs b/server/src/parsing.rs index 6cc2baf..b585c8e 100644 --- a/server/src/parsing.rs +++ b/server/src/parsing.rs @@ -12,6 +12,7 @@ use crate:: info, debug, warn, + UnwrapOrExit, }; mod strings; @@ -93,10 +94,10 @@ pub fn token_parse( "or" => { info!("OR command, jumping over"); - index += match strings::closing_char(&tokens[index..], '{','}') // TODO eh + index += match strings::closing_char(&tokens[index..], '{','}') { - Ok(index) => index, - Err(()) => return Err(String::from("Unable to find closing brace to OR command")), + Some(index) => index, + None => return Err(String::from("No closing brace")), }; continue }, @@ -130,12 +131,16 @@ fn choice_parse let mut choices: Vec = Vec::new(); let mut choice_indeces: Vec = Vec::new(); // Ensure the index is valid (the index is not beyond the vector) + // Get the initial choice let (choice_string, counter) = strings::extract_quoted(&tokens[sum_index..]) .ok_or_else(|| "No choice string".to_string())?; sum_index += counter; choices.push(choice_string); choice_indeces.push(sum_index+1); - sum_index += strings::closing_char(&tokens[sum_index..], '{','}').unwrap() + 1; //TODO eh + sum_index += strings::closing_char(&tokens[sum_index..], '{','}') + .ok_or_else(|| "No closing brace".to_string())? + 1; + // Find all the alternate choices labelled with OR + // Fill out the choices vector with all the choice strings while tokens[sum_index].to_lowercase() == "or" { let (choice_string, counter) = strings::extract_quoted(&tokens[sum_index+1..]) @@ -143,14 +148,17 @@ fn choice_parse sum_index += counter; choices.push(choice_string); choice_indeces.push(sum_index+2); - sum_index += strings::closing_char(&tokens[sum_index..], '{','}').unwrap() + 1; //TODO eh + sum_index += strings::closing_char(&tokens[sum_index..], '{','}') + .ok_or_else(|| "No closing brace".to_string())? + 1; } debug!("{choices:?}"); - let mut data = data_to_send.lock().unwrap(); + // Send the choices to the Client via the API + let mut data = data_to_send.lock().unwrap_or_exit("Data to send Mutex was poisoned",2); data.action_type = String::from("choice"); data.content = String::new(); data.character = String::new(); - data.choices = choices; //TODO + data.choices = choices; drop(data); + // Return the choice indeces Ok((sum_index + 1, choice_indeces)) } diff --git a/server/src/parsing/character_parse.rs b/server/src/parsing/character_parse.rs index 5067b89..68d5a94 100644 --- a/server/src/parsing/character_parse.rs +++ b/server/src/parsing/character_parse.rs @@ -4,6 +4,7 @@ use crate:: // Internal code character, api, + UnwrapOrExit, //Libs Mutex, Arc, @@ -43,7 +44,7 @@ pub fn character_parse { debug!("{output_string}"); sum_index += counter; - let mut data = data_to_send.lock().unwrap(); + let mut data = data_to_send.lock().unwrap_or_exit("Data to send Mutex was poisoned", 2); data.action_type = String::from("output"); data.content = output_string; data.character = character_name; @@ -68,12 +69,12 @@ pub fn character_parse None => return Err(("Unable to parse property to change character".to_string(),sum_index)), }; info!("CHANGE command with character {character_name} feature {feature}"); - let mut characters = characters.lock().expect("Data cannot be unlocked"); + let mut characters = characters.lock().unwrap_or_exit("Character Mutex was poisoned",3); if let Some(character) = characters.get_mut(&character_name) && character.set_field(feature, &output_string) .is_err() { warn!("Feature {feature} does not exist") } drop(characters); - let mut data = data_to_send.lock().unwrap(); // TODO eh? + let mut data = data_to_send.lock().unwrap_or_exit("Data to send Mutex was poisoned",2); // TODO eh? data.action_type = String::from("change"); data.content = String::new(); data.character = character_name; diff --git a/server/src/parsing/strings.rs b/server/src/parsing/strings.rs index 6545911..b9ed60f 100644 --- a/server/src/parsing/strings.rs +++ b/server/src/parsing/strings.rs @@ -1,5 +1,5 @@ pub fn closing_char(parts: &[&str], open: char, close: char) --> Result +-> Option { let mut indentation: usize = 0; let mut flag = false; // flag to mark you've passed open @@ -11,9 +11,9 @@ pub fn closing_char(parts: &[&str], open: char, close: char) flag = true; } if part.contains(close) { indentation -= 1; } - if indentation == 0 && flag { return Ok(index); } + if indentation == 0 && flag { return Some(index); } } - Err(()) + None } pub fn extract_quoted(parts: &[&str]) -> Option<(String, usize)> diff --git a/server/src/traits.rs b/server/src/traits.rs new file mode 100644 index 0000000..c1b42e0 --- /dev/null +++ b/server/src/traits.rs @@ -0,0 +1,23 @@ +use crate:: +{ + error, + exit, +}; + +pub trait UnwrapOrExit +{ + fn unwrap_or_exit(self, error_message: &str, error_code: i32) -> T; +} + +impl UnwrapOrExit for Result +{ + fn unwrap_or_exit(self, error_message: &str, error_code: i32) -> T + { + if let Ok(value) = self { value } + else + { + error!("{error_message}"); + exit(error_code); + } + } +} diff --git a/stories/test.zip b/stories/test.zip index a14af52b4198307983bf6800092e7b3eb6957d50..458becd7b96802d3fa49768c6548b756d9d17fb5 100644 GIT binary patch delta 142 zcmeyu@`Z&rz?+#xgn@y9gF$1~`pKM(a_rj4>{;5$?348v`?+CqPo}P)$g9dO6T_aR z62m^x@+dDOlN>WbpFEQ^h{I4^l3!G*mysA6!pgv`oy