diff --git a/Cargo.toml b/Cargo.toml index 4c294fd..c5e91c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,5 @@ members = [ "shared", "server", "complex", + "cli" ] diff --git a/README.md b/README.md index 9e6a383..f305447 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,16 @@ To build and the complex library (used by other components): cargo build -p complex ``` +## Running the worker with CLI + +To run the worker with CLI, use the following command: + +You can read the CLI rustdoc documentation for more information on the CLI arguments. + +```bash +cargo run -p client -- -h +``` + ## Documentation To generate documentation for all packages without including dependencies (recommended): diff --git a/cli/Cargo.toml b/cli/Cargo.toml new file mode 100644 index 0000000..91c5432 --- /dev/null +++ b/cli/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "cli" +version = "0.1.0" +edition = "2021" +authors = ["James ", "Ronan ", "Charles ", "Samira "] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "4.4.6", features = ["derive"] } diff --git a/cli/src/lib.rs b/cli/src/lib.rs new file mode 100644 index 0000000..67c567f --- /dev/null +++ b/cli/src/lib.rs @@ -0,0 +1 @@ +pub mod parser; diff --git a/cli/src/parser.rs b/cli/src/parser.rs new file mode 100644 index 0000000..fef5e50 --- /dev/null +++ b/cli/src/parser.rs @@ -0,0 +1,22 @@ +pub use clap::Parser; + +/// # Command line arguments for the CLI +/// +/// > This struct is used to parse the command line arguments +/// +/// ## Example +/// +/// ```sh +/// worker -H 192.168.1.0 -P 3000 -N my_group_name +/// ``` +#[derive(Parser, Debug)] +pub struct CliArgs { + #[clap(short = 'H', long = "hostname", default_value = "localhost")] + pub hostname: String, + + #[clap(short = 'P', long = "port", default_value = "8787")] + pub port: u16, + + #[clap(short = 'N', long = "name", default_value = "worker")] + pub worker_name: String, +} diff --git a/client/Cargo.toml b/client/Cargo.toml index cf6d312..cfec729 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -11,3 +11,4 @@ image = { version = "0.24.7", features = [] } complex = { path = "../complex" } shared = { path = "../shared" } server = { path = "../server" } +cli = { path = "../cli" } diff --git a/client/src/client.rs b/client/src/client.rs deleted file mode 100644 index 1bcf58b..0000000 --- a/client/src/client.rs +++ /dev/null @@ -1,32 +0,0 @@ -use server::services::{connect::connect, write::write}; - -/// Connect to the server and send a message -/// -/// # Arguments -/// -/// * `host` - Hostname -/// * `port` - Port -/// -/// # Return -/// -/// * `Result` - TcpStream -/// -/// # Example -/// -/// ``` -/// use client::client::connect_server; -/// -/// let stream = connect_server("localhost", "8080"); -/// ``` -/// -/// # Panic -/// -/// * `std::io::Error` - If the connection failed -/// -pub fn connect_server(host: &str, port: &str) -> std::io::Result { - let stream = connect(format!("{}:{}", host, port))?; - - write(stream, "Hello World !")?; - - Ok(()) -} diff --git a/client/src/main.rs b/client/src/main.rs index ea5d159..e870a2b 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,9 +1,13 @@ mod image; mod julia; +use std::io; + use crate::image::open_image; use crate::julia::generate_julia_set; +use cli::parser::{CliArgs, Parser}; +use server::services::{connect::connect, reader::read_message}; use shared::types::filesystem::FileExtension; use shared::types::fractal_descriptor::FractalType::Julia; use shared::types::fractal_descriptor::{FractalDescriptor, JuliaDescriptor}; @@ -14,7 +18,11 @@ use shared::types::u8data::U8Data; use shared::types::{complex::Complex, resolution::Resolution}; use shared::utils::filesystem::{get_dir_path_buf, get_extension_str, get_file_path}; -fn main() { +fn main() -> io::Result<()> { + let args: CliArgs = CliArgs::parse(); + let stream = connect(format!("{}:{}", args.hostname, args.port).as_str())?; + let message = read_message(stream); + println!("{}", message); let img_path = get_file_path( "julia", get_dir_path_buf(), @@ -54,4 +62,6 @@ fn main() { } open_image(img_path.as_str()); + + Ok(()) } diff --git a/client/src/mod.rs b/client/src/mod.rs index 62881d8..c3c410d 100644 --- a/client/src/mod.rs +++ b/client/src/mod.rs @@ -1,2 +1,3 @@ -pub mod client; +pub mod image; pub mod julia; +pub mod networking; diff --git a/client/src/networking.rs b/client/src/networking.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/client/src/networking.rs @@ -0,0 +1 @@ + diff --git a/server/src/services/connect.rs b/server/src/services/connect.rs index 1ac1e2c..2de7377 100644 --- a/server/src/services/connect.rs +++ b/server/src/services/connect.rs @@ -1,4 +1,4 @@ -use std::io::Result; +use std::io; use std::net::TcpStream; /// Connect to a server @@ -10,7 +10,7 @@ use std::net::TcpStream; /// # Return /// /// * `Result` - TcpStream -pub fn connect(address: &str) -> Result { +pub fn connect(address: &str) -> io::Result { let stream = TcpStream::connect(address)?; Ok(stream) diff --git a/server/src/services/mod.rs b/server/src/services/mod.rs index 7f9fdb2..83fb340 100644 --- a/server/src/services/mod.rs +++ b/server/src/services/mod.rs @@ -1,2 +1,3 @@ pub mod connect; +pub mod reader; pub mod write; diff --git a/server/src/services/reader.rs b/server/src/services/reader.rs new file mode 100644 index 0000000..d05e7bf --- /dev/null +++ b/server/src/services/reader.rs @@ -0,0 +1,45 @@ +use std::{io::Read, net::TcpStream}; + +/// Read a message from a TCP stream. +/// +/// This function reads data from the given TCP stream up to 1024 bytes. +/// It assumes that the message is UTF-8 encoded. If the message contains +/// non-UTF-8 bytes, they will be replaced by U+FFFD REPLACEMENT CHARACTER. +/// The function also trims null characters from the message. +/// +/// # Arguments +/// +/// * `stream` - A mutable reference to the TCP stream from which to read the message. +/// +/// # Returns +/// +/// Returns a `String` containing the message read from the stream. +/// +/// # Examples +/// +/// ```no_run +/// use std::net::{TcpListener, TcpStream}; +/// use server::services::reader::read_message; +/// +/// let listener = TcpListener::bind("127.0.0.1:0").unwrap(); +/// let address = listener.local_addr().unwrap(); +/// let mut stream = TcpStream::connect(address).unwrap(); +/// +/// let message = read_message(stream); +/// println!("Received message: {}", message); +/// ``` +/// +/// # Panics +/// +/// Panics if the reading from the stream fails or if the buffer cannot be +/// converted to a UTF-8 string. +/// +pub fn read_message(mut stream: TcpStream) -> String { + let mut buffer = [0; 1024]; + stream.read(&mut buffer).unwrap(); + + let message = String::from_utf8_lossy(&buffer[..]); + let message = message.trim_matches(char::from(0)).to_string(); + + message +} diff --git a/server/src/services/write.rs b/server/src/services/write.rs index 3e92d48..861af6b 100644 --- a/server/src/services/write.rs +++ b/server/src/services/write.rs @@ -12,6 +12,17 @@ use std::net::TcpStream; /// # Return /// /// * `Result` - TcpStream +/// +/// # Example +/// +/// ```no_run +/// use std::net::TcpStream; +/// use server::services::write::write; +/// +/// let stream = TcpStream::connect("localhost:8787").unwrap(); +/// let stream = write(stream, "Hello world!").unwrap(); +/// ``` +/// pub fn write(mut stream: TcpStream, message: &str) -> Result { stream.write(format!("${}", message).as_bytes())?;