From 1c45e1dd704b51c3d8aed551706b4a070ccfa281 Mon Sep 17 00:00:00 2001 From: Viktor Persson Date: Thu, 2 May 2024 13:21:16 +0200 Subject: [PATCH] Add to_hashmap(). --- Cargo.toml | 20 ++++++++++++++++++++ src/lib.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/util.rs | 27 +++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/lib.rs create mode 100644 src/util.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..221d6b2 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "quake_infostring" +description = "Parse QuakeWorld info strings." +categories = ["parsing"] +keywords = ["quake", "quakeworld"] +repository = "https://github.com/vikpe/quake_infostring" +authors = ["Viktor Persson "] +version = "0.1.0" +edition = "2021" +license = "MIT" +include = [ + "/Cargo.toml", + "/README.md", + "/benches/**", + "/src/**", +] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dev-dependencies] +pretty_assertions = "1.4.0" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..7fc7503 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,49 @@ +use std::collections::HashMap; + +mod util; + +pub const DELIMITER: char = '\\'; + +pub fn to_hashmap(serverinfo: &str) -> HashMap { + let serverinfo_ = util::clean(serverinfo); + let mut iter = serverinfo_ + .trim_matches(DELIMITER) + .split(DELIMITER) + .map(|v| v.to_string()); + let mut result = HashMap::new(); + + while let Some(key) = iter.next() { + if let Some(value) = iter.next() { + result.insert(key, value); + } + } + + result +} + +#[cfg(test)] +mod tests { + use pretty_assertions::assert_eq; + + use super::*; + + #[test] + fn test_to_hashmap() { + // unbalanced string + { + let result = to_hashmap(r#"\maxfps\77"#); + assert_eq!(result.get("maxfps"), Some(&"77".to_string())); + assert_eq!(result.get("matchtag"), None); + } + + // valid string + { + let result = to_hashmap(r#"\maxfps\77\matchtag\kombat\epoch\123456"#); + assert_eq!(result.get("maxfps"), Some(&"77".to_string())); + assert_eq!(result.get("matchtag"), Some(&"kombat".to_string())); + assert_eq!(result.get("epoch"), Some(&"123456".to_string())); + + assert_eq!(result.get("MISSING_KEY"), None); + } + } +} diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..be5f332 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,27 @@ +use crate::DELIMITER; + +pub fn clean(serverinfo: &str) -> String { + serverinfo + .trim() + .trim_end_matches(r#"\n"#) + .replace(r#"\\"#, &DELIMITER.to_string()) + .replace('"', "") + .trim_end_matches(DELIMITER) + .to_string() +} + + +#[cfg(test)] +mod tests { + use pretty_assertions::assert_eq; + + use super::*; + + #[test] + fn test_clean() { + assert_eq!(clean(r#"\\maxfps\\77"#), r#"\maxfps\77"#); // double slashes + assert_eq!(clean(r#"\maxfps\77\"#), r#"\maxfps\77"#); // trailing slash + assert_eq!(clean(r#" \needpass\1\\\n "#), r#"\needpass\1"#); // whitespace + assert_eq!(clean(r#"\max"fps\77""#), r#"\maxfps\77"#); // quotes + } +}