How do I use getopts opts_present?

I want to check if any of the options flags got matched, and if it not, print something, so after reading the docs I found this: getopts::Matches - Rust , it says that it returns true if any of several options were matched. My logic thinks that it should take a list of options, so I tried it:

use getopts::Options;
use std::env;

fn main() {
    println!("Hello, world!");

    let args: Vec<String> = env::args().collect();
    let arg_len = args.len();
    println!("Arg amount: {}",arg_len);
    println!("{:?}",args);

    let mut opts = Options::new();
    opts.optflag("r", "eat-ramen", "Eat some ramen noodles");
    opts.optflag("p", "eat-pho", "Eat some pho noodles");

    println!("{}",opts.usage(""));

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => {m}
        Err(f) => {panic!(f.to_string())}
    };

    let opt_list = ["r","p"];

    if !(matches.opts_present(&opt_list)){
        println!("You are not hungry");
        return
    }
}

and then it complained that it expected slice, found array. So how do I pass in list of options?

["x"] is an array. &["x"][..] makes it a slice. Try &opt_list[..].

It doesn't work for me, if I changed it into

use getopts::Options;
use std::env;

fn main() {
    println!("Hello, world!");

    let args: Vec<String> = env::args().collect();
    let arg_len = args.len();
    println!("Arg amount: {}",arg_len);
    println!("{:?}",args);

    let mut opts = Options::new();
    opts.optflag("r", "eat-ramen", "Eat some ramen noodles");
    opts.optflag("p", "eat-pho", "Eat some pho noodles");

    println!("{}",opts.usage(""));

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => {m}
        Err(f) => {panic!(f.to_string())}
    };

    let opt_list = ["r","p"];

    if !(matches.opts_present(&opt_list[..])){
        println!("You are not hungry");
        return
    }
}

the compiler errors like this:

byakuya@seireitei ~/D/r/rust_getopts_test (master) [101]> cargo run
   Compiling rust_getopts_test v0.1.0 (/home/byakuya/Development/rusttest/rust_getopts_test)
error[E0308]: mismatched types
  --> src/main.rs:25:31
   |
25 |     if !(matches.opts_present(&opt_list[..])){
   |                               ^^^^^^^^^^^^^ expected struct `std::string::String`, found `&str`
   |
   = note: expected reference `&[std::string::String]`
              found reference `&[&str]`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: could not compile `rust_getopts_test`.

To learn more, run the command again with --verbose.

What works for me is to add .to_owned to the string literals inside opt_list:

use getopts::Options;
use std::env;

fn main() {
    println!("Hello, world!");

    let args: Vec<String> = env::args().collect();
    let arg_len = args.len();
    println!("Arg amount: {}",arg_len);
    println!("{:?}",args);

    let mut opts = Options::new();
    opts.optflag("r", "eat-ramen", "Eat some ramen noodles");
    opts.optflag("p", "eat-pho", "Eat some pho noodles");

    println!("{}",opts.usage(""));

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => {m}
        Err(f) => {panic!(f.to_string())}
    };

    let opt_list = ["r".to_owned(),"p".to_owned()];

    if !(matches.opts_present(&opt_list)){
        println!("You are not hungry");
        return
    }
}

Output:

byakuya@seireitei ~/D/r/rust_getopts_test (master) [101]> cargo run
   Compiling rust_getopts_test v0.1.0 (/home/byakuya/Development/rusttest/rust_getopts_test)
    Finished dev [unoptimized + debuginfo] target(s) in 0.72s
     Running `target/debug/rust_getopts_test`
Hello, world!
Arg amount: 1
["target/debug/rust_getopts_test"]


Options:
    -r, --eat-ramen     Eat some ramen noodles
    -p, --eat-pho       Eat some pho noodles

You are not hungry
byakuya@seireitei ~/D/r/rust_getopts_test (master)> cargo run -- -p
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/rust_getopts_test -p`
Hello, world!
Arg amount: 2
["target/debug/rust_getopts_test", "-p"]


Options:
    -r, --eat-ramen     Eat some ramen noodles
    -p, --eat-pho       Eat some pho noodles

which is what I expects. But adding .to_owned() to all strings literals is annoying, is there a way to make it simpler?

opts_present wants owned strings. That's an unusual choice for such method, but if it wants them this way, there's no way around that. Owned strings and string views have different layout in memory, so you can't simply cast one to another.

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.