diff --git a/Cargo.lock b/Cargo.lock index 27fd152..2c495cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,131 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.5.0", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener 5.4.1", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-std" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" +dependencies = [ + "async-channel 1.9.0", + "async-global-executor", + "async-io", + "async-lock", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + [[package]] name = "base64" version = "0.22.1" @@ -35,6 +160,19 @@ version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a" +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel 2.5.0", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + [[package]] name = "bumpalo" version = "3.20.3" @@ -76,8 +214,9 @@ dependencies = [ [[package]] name = "clean_file" -version = "0.8.3" +version = "0.8.4" dependencies = [ + "async-std", "futures", "serde", "serde_json", @@ -86,6 +225,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "const_format" version = "0.2.36" @@ -125,6 +273,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "deranged" version = "0.5.8" @@ -157,6 +311,33 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener 5.4.1", + "pin-project-lite", +] + [[package]] name = "fastrand" version = "2.4.1" @@ -248,6 +429,19 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.32" @@ -302,6 +496,18 @@ dependencies = [ "wasip3", ] +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "hashbrown" version = "0.15.5" @@ -323,6 +529,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + [[package]] name = "id-arena" version = "2.3.0" @@ -391,6 +603,15 @@ version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "leb128fmt" version = "0.1.0" @@ -423,6 +644,9 @@ name = "log" version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" +dependencies = [ + "value-bag", +] [[package]] name = "memchr" @@ -500,6 +724,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.5" @@ -529,12 +759,43 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -916,6 +1177,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "value-bag" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" + [[package]] name = "vcpkg" version = "0.2.15" @@ -959,6 +1226,16 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.122" diff --git a/Cargo.toml b/Cargo.toml index 6443b21..2394ca2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clean_file" -version = "0.8.3" +version = "0.8.4" edition = "2024" rust-version = "1.95" @@ -14,3 +14,4 @@ textsender_models = { git = "ssh://git@git.kundeng.us/phoenix/textsender-models. [dev-dependencies] tempfile = { version = "3.27.0" } +async-std = { version = "1.13.2" } diff --git a/src/main.rs b/src/main.rs index 0503ddf..d4fbe0f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,7 +23,7 @@ async fn main() { match prsr.file_dump().await { Ok(contacts) => { prsr.print_phone_numbers(&contacts); - prsr.save_file(contacts).await; + prsr.save_file(contacts, parser::DEFAULT_OUTPUT_FILE).await; } Err(err) => { eprintln!("Error: {err:?}"); diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 9239aa8..afb26a2 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,5 +1,6 @@ use std::io::BufRead; +pub const DEFAULT_OUTPUT_FILE: &str = "numbers.json"; const LETTERS: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; #[derive(Clone, Debug, Default)] @@ -40,11 +41,13 @@ impl NumberParser { } } - pub async fn save_file(&self, numbers: Vec) { - let filename = String::from("numbers.json"); - + pub async fn save_file( + &self, + numbers: Vec, + filename: &str, + ) { match serde_json::to_string(&numbers) { - Ok(json_string) => match std::fs::write(&filename, json_string) { + Ok(json_string) => match std::fs::write(filename, json_string) { Ok(_) => { println!("Saved to: {filename:?}"); } @@ -166,3 +169,99 @@ impl NumberParser { parsed } } + +#[cfg(test)] +mod tests { + use textsender_models::contact::Contact; + + const TEST_NUMBERS_0: &str = "tests/numbers-0.txt"; + + #[test] + fn test_file_dump() { + let file_exists = { + let path = std::path::Path::new(TEST_NUMBERS_0); + path.exists() + }; + + assert_eq!(true, file_exists, "File does not exists {TEST_NUMBERS_0:?}"); + + let filename = String::from(TEST_NUMBERS_0); + let prsr = super::NumberParser { filepath: filename }; + let original: Vec = vec![ + Contact { + phone_number: String::from("+13055550112"), + ..Default::default() + }, + Contact { + phone_number: String::from("+13175550123"), + ..Default::default() + }, + Contact { + phone_number: String::from("+14155550135"), + ..Default::default() + }, + Contact { + phone_number: String::from("+16085550190"), + ..Default::default() + }, + Contact { + phone_number: String::from("+17135550167"), + ..Default::default() + }, + Contact { + phone_number: String::from("+16025550177"), + ..Default::default() + }, + Contact { + phone_number: String::from("+13605550158"), + ..Default::default() + }, + Contact { + phone_number: String::from("+12175550194"), + ..Default::default() + }, + ]; + + match async_std::task::block_on(prsr.file_dump()) { + Ok(contacts) => { + assert!((contacts.len() > 0), "No contacts has been parsed"); + + let phone_numbers_1: std::collections::HashSet<_> = + contacts.iter().map(|p| p.phone_number.clone()).collect(); + let phone_numbers_2: std::collections::HashSet<_> = + original.iter().map(|p| p.phone_number.clone()).collect(); + assert_eq!(phone_numbers_1, phone_numbers_2, "No match"); + } + Err(err) => { + assert!(false, "Error: {err:?}"); + } + }; + } + + #[test] + fn test_save_file() { + let prsr = super::NumberParser { + filepath: String::from(TEST_NUMBERS_0), + }; + let results = async_std::task::block_on(prsr.file_dump()); + assert!(results.is_ok(), "File dump not successful"); + let test_output_file: &str = "test-numbers.json"; + + let contacts = results.unwrap(); + async_std::task::block_on(prsr.save_file(contacts, test_output_file)); + let file_exists = { + let path = std::path::Path::new(test_output_file); + path.exists() + }; + + assert!(file_exists, "Contacts were not saved"); + match std::fs::remove_file(test_output_file) { + Ok(_) => { + println!("File removed"); + } + Err(err) => { + assert!(false, "Error: {err:?}"); + } + } + } +} diff --git a/tests/numbers.txt b/tests/numbers-0.txt similarity index 100% rename from tests/numbers.txt rename to tests/numbers-0.txt