7

I have used clap crate to parsing arguments in my code. Minimal structure of my code about defining and parsing arguments are as follow.

use clap::builder::Command;
use clap::{Arg, ArgMatches};

let matches = Command::new("test")
                .arg(Arg::new("mass")
                    .short('m')
                    .takes_value(true))
                .get_matches()
let mass: f64 = *matches.get_one::<f64>("mass").unwrap();

But I face an error "thread 'main' panicked at 'Mismatch between definition and access of mass. Could not downcast to f64, need to downcast to alloc::string::String"

I can fix it by using parse() from String to f64.

let mass: f64 = *matches.get_one::<String>("mass").unwrap().parse().unwrap();

I want to know that why only f64 cannot be parsed by get_one function differ from the case of boolean or usize.

StatPhy
  • 121
  • 4
  • It may help to point out that the first code snippet can be built successfully, but when you run it like `./binary -m 0`, it will just panic – Steve Lau Jul 02 '22 at 01:21
  • Yes. The error I faced is a panic. But, I don't know why and how to solve it. – StatPhy Jul 02 '22 at 05:58

2 Answers2

4

I found why the panic occurs, and how to prevent panic. The panic occurs because clap does not detect floating point type argument automatically. We should specify the value parser (or equivalently the type of argument) to clap (at the time we define command) for floating point or other custom types.

let matches = Command::new("test")
                .arg(Arg::new("mass")
                    .short('m')
                    .takes_value(true))
                    .value_parser(clap::value_parser!(f64))
                .get_matches()

Then, the panic is resolved. In the above code block, the result of clap::value_parser!(f64) is _AnonymousValueParser(ValueParser::other(f64))

StatPhy
  • 121
  • 4
0

In my case, it was simply failing to parse the value as the provided type (and displaying a not-very-helpful error message). The type I was trying to parse it as was &str:

matches.get_one::<&str>("arg");

This was making the programme panic, as it fails to parse the input as &str. The solution I used was to parse as String and then convert it to a &str:

matches.get_one::<String>("arg").map(|s| s.as_str());
Jake Ireland
  • 543
  • 4
  • 11