Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.3 support for Option<Vec<T>> #285

Closed
ryankurte opened this issue Nov 26, 2019 · 2 comments
Closed

v0.3 support for Option<Vec<T>> #285

ryankurte opened this issue Nov 26, 2019 · 2 comments

Comments

@ryankurte
Copy link

hey thanks for making a super useful crate!

i've just updated from v0.2.x to v0.3.x and am running into a problem with parsing vectors that i'm not sure how to resolve.

In v0.2.x the following is valid, and passing an option -d something ends up with a vector containing something.

#[derive(Debug, Clone, PartialEq, StructOpt)]
pub struct Options {
    #[structopt(short = "d", long = "data", parse(from_str = "data_from_str"))]
    /// Data as a string
    pub data: Option<Vec<u8>>,
}

pub fn data_from_str(s: &str) -> Vec<u8> {
    s.as_bytes().to_vec()
}

In v0.3.x this results in an error from structopt derive

#[derive(Debug, Clone, PartialEq, StructOpt)]
pub struct Options {
    #[structopt(short = "d", long = "data", parse(from_str = data_from_str))]
    /// Data as a string
    pub data: Option<Vec<u8>>,
}

pub fn data_from_str(s: &str) -> Vec<u8> {
    s.as_bytes().to_vec()
}
error[E0308]: mismatched types
 --> src/main.rs:8:15
  |
8 |     pub data: Option<Vec<u8>>,
  |               ^^^^^^ expected u8, found struct `std::vec::Vec`
  |
  = note: expected type `std::vec::Vec<u8>`
             found type `std::vec::Vec<std::vec::Vec<u8>>`

error: aborting due to previous error

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

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

is it still possible to achieve this in v0.3.x?

@CreepySkeleton
Copy link
Collaborator

CreepySkeleton commented Nov 27, 2019

This is because Option<Vec<T>> is a special case now, it's different from Option<T>.

To suppress this special casing you can use a type alias, as described in changelog

type Something = Vec<u8>;

#[derive(StructOpt)]
struct Opt {
    #[structopt(short = "d", long = "data", parse(from_str = data_from_str))]
    /// Data as a string
    pub data: Option<Something>,
}

structopt doesn't know anything about Something so it'll be counted as Option<T>, just like in structopt v0.2. Alternatively, you can address Vec as std::vec::Vec, structopt doesn't know anything about it pretty much for the same reason.

Also, pay attention that you don't need #[structopt(short = "d")] anymore, use #[structopt(short)] instead, the option's name will be deduced from the field. The same applies to long. Take a look at the docs.

@ryankurte
Copy link
Author

Ahh that's the one, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants