diff --git a/src/cli.rs b/src/cli.rs index 5c75ce3..6841d4d 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -52,6 +52,14 @@ pub enum Commands { #[arg()] args: Vec, + /// Keyword argument for the call. To enforce value is always a string, send value in quotes e.g."'1'" or '"true"'. (May be provided multiple times) + #[arg(short = 'k', long = "kwarg", value_name = "KEY=VALUE")] + kwargs: Vec, + + /// WAMP call option (May be provided multiple times) + #[arg(short = 'o', long = "option", value_name = "KEY=VALUE")] + options: Vec, + /// Number of times to repeat the call per session #[arg(long, default_value_t = 1)] repeat: u32, diff --git a/src/commands/call.rs b/src/commands/call.rs index d93e50d..6332128 100644 --- a/src/commands/call.rs +++ b/src/commands/call.rs @@ -4,10 +4,22 @@ use std::sync::Arc; use tokio::sync::Semaphore; use xconn::sync::CallRequest; -/// Builds a CallRequest from the procedure name and parsed arguments. -fn build_call_request(procedure: &str, args: &[String]) -> CallRequest { - let mut request = CallRequest::new(procedure); - for arg in args { +/// Parses a "key=value" string and returns the key and parsed value. +fn parse_key_value(input: &str) -> Option<(String, ParsedArg)> { + let parts: Vec<&str> = input.splitn(2, '=').collect(); + if parts.len() == 2 { + Some((parts[0].to_string(), parse_arg(parts[1]))) + } else { + None + } +} + +/// Builds a CallRequest from the CallConfig. +fn build_call_request(config: &CallConfig) -> CallRequest { + let mut request = CallRequest::new(&config.procedure); + + // Add positional arguments + for arg in &config.args { request = match parse_arg(arg) { ParsedArg::Integer(v) => request.arg(v), ParsedArg::Float(v) => request.arg(v), @@ -15,6 +27,31 @@ fn build_call_request(procedure: &str, args: &[String]) -> CallRequest { ParsedArg::String(v) => request.arg(v), }; } + + // Add keyword arguments + for kwarg in &config.kwargs { + if let Some((key, value)) = parse_key_value(kwarg) { + request = match value { + ParsedArg::Integer(v) => request.kwarg(&key, v), + ParsedArg::Float(v) => request.kwarg(&key, v), + ParsedArg::Boolean(v) => request.kwarg(&key, v), + ParsedArg::String(v) => request.kwarg(&key, v), + }; + } + } + + // Add options + for opt in &config.options { + if let Some((key, value)) = parse_key_value(opt) { + request = match value { + ParsedArg::Integer(v) => request.option(&key, v), + ParsedArg::Float(v) => request.option(&key, v), + ParsedArg::Boolean(v) => request.option(&key, v), + ParsedArg::String(v) => request.option(&key, v), + }; + } + } + request } @@ -33,7 +70,7 @@ async fn run_session( }; for iteration in 0..call_config.repeat { - let request = build_call_request(&call_config.procedure, &call_config.args); + let request = build_call_request(&call_config); match session.call(request).await { Ok(result) => { diff --git a/src/config.rs b/src/config.rs index 69e3f64..3c48e27 100644 --- a/src/config.rs +++ b/src/config.rs @@ -110,6 +110,8 @@ impl From<&Cli> for ConnectionConfig { pub struct CallConfig { pub procedure: String, pub args: Vec, + pub kwargs: Vec, + pub options: Vec, pub repeat: u32, pub parallel: u32, pub concurrency: usize, diff --git a/src/main.rs b/src/main.rs index 7c93fab..e421c8c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,8 @@ async fn main() -> Result<(), Box> { Commands::Call { procedure, args, + kwargs, + options, repeat, parallel, concurrency, @@ -26,6 +28,8 @@ async fn main() -> Result<(), Box> { let call_config = CallConfig { procedure, args, + kwargs, + options, repeat, parallel, concurrency,