Command line parser Clap: multi args for different type

I'm currently attempting to develop a command-line parser using clap.
However, I've encountered difficulty in representing the following behavior:

cargo run -- --port <PORT> --replicaof <MASTER_HOST> <MASTER_PORT>

Here, <PORT> is expected to be a u16, <MASTER_HOST> is a string, and <MASTER_PORT> is another u16.
Essentially, what I'm seeking is something that looks like this:

#[derive(Parser)]
struct RedisArgs {
    /// Set the server's port
    #[arg(long, default_value = "6379")]
    port: u16,
    /// Set server to replica
    #[arg(long)]
    replicaof: Option<(String ,u16)>,
}

However, I've encountered an issue where clap fails to compile with this structure.

Using Vec<String> as an alternative means all arguments are treated as strings, which is not what I want, especially for the port argument.

Is there a solution to this problem, or must I resort to the Vec method?

If you are okay providing your --replicaof as <MASTER_HOST>:<MASTER_PORT> instead of <MASTER_HOST> <MASTER_PORT>, I think a custom value_parser should work:

#[derive(Parser)]
struct RedisArgs {
    /// Set the server's port
    #[arg(long, default_value = "6379")]
    port: u16,
    /// Set server to replica
    #[arg(long, value_parser = parse_host)]
    replicaof: Option<(String ,u16)>,
}

fn parse_host(s: &str) -> anyhow::Result<(String, u16)> {
    let mut split = s.split(':');
    let host = split.next().unwrap().to_owned();
    let port = split.next().unwrap().parse()?;
    
    Ok((host, port))
}

No, I am not able to do that because I am currently doing the Codecrafter's course. It requires me to handle this specific situation.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.