Skip to content

mapping non-trivial enum to arg group - failing with "all have default" #3711

Answered by epage
RustyJoeM asked this question in Q&A
mapping non-trivial enum to arg group - failing with "all have default" #3711
May 9, 2022 · 1 answers · 1 reply

Hello,

i have trouble mapping non trivial enum like:

pub enum ConfigWaypoint {
    Datastore(Datastore),
    Url(String),
}

// does have impl FromStr...
pub enum Datastore {
    Running,
    Candidate,
    Other(String),
}

to a group of args usable in REPL... First step is modelling Clap struct args to be able to create instance of above enum for further processing by sub-crate calls etc.

ConfigWaypoint is used in multiple places of my codebase, so having some wrapping Clap struct would be great for reuse, but i am failing even with explicit args currently.

I stumbled upon several closed issues & discussions from the past mentioning e.g. default_missing_value that seems not to exist anymore...

To map enum to CLAP struct, i tried adding all of its "variants" as standalone Option<_> fields...
I try this command definition:

pub enum NetconfCommand {
    ...
    #[clap(group(
        ArgGroup::new("from")
            .required(true)
            .args(&["from_datastore", "from_url"]),
    ))]
    CopyConfig {
        from_datastore: Option<Datastore>,
        from_url: Option<String>,
    },
    ....
}

and i end up with runtime panic when i try to run command with no args (i expect help printout with needed args description instead of panic):

netconf-cli$ copy-config
022-05-09 19:40:21.5851619 +00:00:00thread 'main' panicked at 'Command copy-config: Argument group 'from' is required but all of it's arguments have a default value.', ...\.cargo\registry\src\github.com-1ecc6299db9ec823\clap-3.1.15\src\build\debug_asserts.rs:256:13

The mentioned types do NOT derive or implement Default trait AFAIK.
Above feels kind of weird, considering Option<_> should take care of having/not having the value set by user in the first place...

Is some part of structure i try to apply incorrect or do i miss some key annotation for my derived Clap structs?

To check, is your ideal solution #2621?

Looks like we have some debug-asserts out of order, making this more confusing. When addressed, it says from_datastore doesn't exist. This might look weird but the reason is that its from-datastore

#!/usr/bin/env -S rust-script --debug

//! ```cargo
//! [dependencies]
//! clap = { path = "../clap", features = ["derive", "debug"] }
//! ```

use clap::Parser;

#[derive(Parser, Debug)]
pub enum Args {
    #[clap(group(
        clap::ArgGroup::new("from")
            .required(true)
            .args(&["from-datastore", "from-url"]),
    ))]
    CopyConfig {
        from_datastore: Option<String>,
        from_url: Option<String>,
    },
}

fn main() {
…

Replies

1 suggested answer
·
1 reply

To check, is your ideal solution #2621?

Looks like we have some debug-asserts out of order, making this more confusing. When addressed, it says from_datastore doesn't exist. This might look weird but the reason is that its from-datastore

#!/usr/bin/env -S rust-script --debug

//! ```cargo
//! [dependencies]
//! clap = { path = "../clap", features = ["derive", "debug"] }
//! ```

use clap::Parser;

#[derive(Parser, Debug)]
pub enum Args {
    #[clap(group(
        clap::ArgGroup::new("from")
            .required(true)
            .args(&["from-datastore", "from-url"]),
    ))]
    CopyConfig {
        from_datastore: Option<String>,
        from_url: Option<String>,
    },
}

fn main() {
    let args = Args::parse();
    dbg!(args);
}

This was fixed in #3708 but that is behind the unstable-v4 feature flag as its a breaking change.

1 reply
@RustyJoeM

Thanks for guidance again :) Changing arg names from underscore_format to dash-format resolved the panic & gives expected help message. I am not sure how the mentioned fix applies for future upgrades - whether the underscore or dash variant of arg name will be valid, but ill know if i run into issue and do quick fix if needed :).

Help message for the above case gets a bit crowded with commands requiring e.g. two or more such enum params, but that's the "input requirement" usability, not CLAPs issue :)

Referenced #2621 gives an example with trivial enum type with no payload, so it's hard for me to say whether it applies (in later phases with extension) to my case or not.

Answer selected by RustyJoeM
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
2 participants