diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-08-23 23:58:15 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-08-23 23:58:15 +0000 |
commit | 4709ca424a6b93a2a4683ebc31951801ad2379e8 (patch) | |
tree | 09fa4d8ab7933bd6aea36bbcd7389cd71e2a373a | |
parent | 4e2b1565c93c96993512b4a90dd2542b823094a5 (diff) | |
parent | 108a00fc514b13e7a79994fa61a90f0f2b265a39 (diff) | |
download | structopt-4709ca424a6b93a2a4683ebc31951801ad2379e8.tar.gz |
Snap for 7668063 from 108a00fc514b13e7a79994fa61a90f0f2b265a39 to simpleperf-release
Change-Id: I835d92e8cc53d5d821785b81474f135015afaecc
-rw-r--r-- | .cargo_vcs_info.json | 2 | ||||
-rw-r--r-- | Android.bp | 14 | ||||
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | Cargo.toml | 8 | ||||
-rw-r--r-- | Cargo.toml.orig | 5 | ||||
-rw-r--r-- | METADATA | 10 | ||||
-rw-r--r-- | examples/enum_in_args_with_strum.rs | 27 | ||||
-rw-r--r-- | examples/example.rs | 2 | ||||
-rw-r--r-- | src/lib.rs | 37 | ||||
-rw-r--r-- | tests/generics.rs | 137 |
10 files changed, 228 insertions, 18 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index 7d10f0d..887fa2d 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,5 @@ { "git": { - "sha1": "8bda3b64daf53f0ed6bb6bee2c767a63c7c477fc" + "sha1": "004cfc218e7fbfdbecc4088f9e3fa5061f36cb4d" } } @@ -60,19 +60,19 @@ rust_library { // atty-0.2.14 // bitflags-1.2.1 "default" // clap-2.33.3 "ansi_term,atty,color,default,strsim,suggestions,vec_map" -// heck-0.3.2 +// heck-0.3.3 // lazy_static-1.4.0 -// libc-0.2.94 +// libc-0.2.98 // proc-macro-error-1.0.4 "default,syn,syn-error" // proc-macro-error-attr-1.0.4 -// proc-macro2-1.0.26 "default,proc-macro" +// proc-macro2-1.0.28 "default,proc-macro" // quote-1.0.9 "default,proc-macro" // strsim-0.8.0 -// structopt-derive-0.4.14 -// syn-1.0.71 "clone-impls,default,derive,full,parsing,printing,proc-macro,quote" +// structopt-derive-0.4.15 +// syn-1.0.74 "clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,quote" // textwrap-0.11.0 -// unicode-segmentation-1.7.1 +// unicode-segmentation-1.8.0 // unicode-width-0.1.8 "default" -// unicode-xid-0.2.1 "default" +// unicode-xid-0.2.2 "default" // vec_map-0.8.2 // version_check-0.9.3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 650afea..117ef2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v0.3.22 (2021-07-04) + +* Add support for [generics in derive](https://github.com/TeXitoi/structopt/issues/128) + # v0.3.21 (2020-11-30) * Fixed [another breakage](https://github.com/TeXitoi/structopt/issues/447) @@ -13,7 +13,7 @@ [package] edition = "2018" name = "structopt" -version = "0.3.21" +version = "0.3.22" authors = ["Guillaume Pinot <texitoi@texitoi.eu>", "others"] description = "Parse command line argument by defining a struct." documentation = "https://docs.rs/structopt" @@ -35,10 +35,14 @@ optional = true package = "paw" [dependencies.structopt-derive] -version = "=0.4.14" +version = "=0.4.15" [dev-dependencies.rustversion] version = "1" +[dev-dependencies.strum] +version = "0.20" +features = ["derive"] + [dev-dependencies.trybuild] version = "1.0.5" features = ["diff"] diff --git a/Cargo.toml.orig b/Cargo.toml.orig index fdad9ef..d45ecac 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "structopt" -version = "0.3.21" +version = "0.3.22" edition = "2018" authors = ["Guillaume Pinot <texitoi@texitoi.eu>", "others"] description = "Parse command line argument by defining a struct." @@ -28,10 +28,11 @@ travis-ci = { repository = "TeXitoi/structopt" } [dependencies] clap = { version = "2.33", default-features = false } -structopt-derive = { path = "structopt-derive", version = "=0.4.14" } +structopt-derive = { path = "structopt-derive", version = "=0.4.15" } lazy_static = "1.4.0" paw_dep = { version = "1", optional = true, package = "paw" } [dev-dependencies] trybuild = { version = "1.0.5", features = ["diff"] } rustversion = "1" +strum = { version = "0.20", features = ["derive"] } @@ -7,13 +7,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/structopt/structopt-0.3.21.crate" + value: "https://static.crates.io/crates/structopt/structopt-0.3.22.crate" } - version: "0.3.21" + version: "0.3.22" license_type: NOTICE last_upgrade_date { - year: 2020 - month: 11 - day: 30 + year: 2021 + month: 8 + day: 9 } } diff --git a/examples/enum_in_args_with_strum.rs b/examples/enum_in_args_with_strum.rs new file mode 100644 index 0000000..a045a48 --- /dev/null +++ b/examples/enum_in_args_with_strum.rs @@ -0,0 +1,27 @@ +use structopt::StructOpt; +use strum::{EnumString, EnumVariantNames, VariantNames}; + +const DEFAULT: &str = "txt"; + +#[derive(StructOpt, Debug)] +struct Opt { + #[structopt( + long, + possible_values = Format::VARIANTS, + case_insensitive = true, + default_value = DEFAULT, + )] + format: Format, +} + +#[derive(EnumString, EnumVariantNames, Debug)] +#[strum(serialize_all = "kebab_case")] +enum Format { + Txt, + Md, + Html, +} + +fn main() { + println!("{:?}", Opt::from_args()); +} diff --git a/examples/example.rs b/examples/example.rs index 7a9a514..71cc124 100644 --- a/examples/example.rs +++ b/examples/example.rs @@ -37,7 +37,7 @@ struct Opt { // An optional list of values, will be `None` if not present on // the command line, will be `Some(vec![])` if no argument is - // provided (i.e. `--optv`) and will be `Some(Some(String))` if + // provided (i.e. `--optv`) and will be `Some(Vec<String>)` if // argument list is provided (e.g. `--optv a b c`). #[structopt(long)] optv: Option<Vec<String>>, @@ -52,6 +52,7 @@ //! - [Flattening subcommands](#flattening-subcommands) //! - [Flattening](#flattening) //! - [Custom string parsers](#custom-string-parsers) +//! - [Generics](#generics) //! //! //! @@ -1053,6 +1054,42 @@ //! In the `try_from_*` variants, the function will run twice on valid input: //! once to validate, and once to parse. Hence, make sure the function is //! side-effect-free. +//! +//! ## Generics +//! +//! Generic structs and enums can be used. They require explicit trait bounds +//! on any generic types that will be used by the `StructOpt` derive macro. In +//! some cases, associated types will require additional bounds. See the usage +//! of `FromStr` below for an example of this. +//! +//! ``` +//! # use structopt::StructOpt; +//! use std::{fmt, str::FromStr}; +//! +//! // a struct with single custom argument +//! #[derive(StructOpt)] +//! struct GenericArgs<T:FromStr> where <T as FromStr>::Err: fmt::Display + fmt::Debug { +//! generic_arg_1: String, +//! generic_arg_2: String, +//! custom_arg_1: T +//! } +//! ``` +//! +//! or +//! +//! ``` +//! # use structopt::StructOpt; +//! // a struct with multiple custom arguments in a substructure +//! #[derive(StructOpt)] +//! struct GenericArgs<T:StructOpt> { +//! generic_arg_1: String, +//! generic_arg_2: String, +//! #[structopt(flatten)] +//! custom_args: T +//! } +//! ``` + + // those mains are for a reason #![allow(clippy::needless_doctest_main)] diff --git a/tests/generics.rs b/tests/generics.rs new file mode 100644 index 0000000..896f98a --- /dev/null +++ b/tests/generics.rs @@ -0,0 +1,137 @@ + +use structopt::StructOpt; + +#[test] +fn generic_struct_flatten() { + + #[derive(StructOpt,PartialEq,Debug)] + struct Inner{ + pub answer: isize + } + + #[derive(StructOpt,PartialEq,Debug)] + struct Outer<T:StructOpt>{ + #[structopt(flatten)] + pub inner: T + } + + assert_eq!( + Outer{inner: Inner{ answer: 42 }}, + Outer::from_iter(&[ "--answer", "42" ]) + ) +} + +#[test] +fn generic_struct_flatten_w_where_clause() { + + #[derive(StructOpt,PartialEq,Debug)] + struct Inner{ + pub answer: isize + } + + #[derive(StructOpt,PartialEq,Debug)] + struct Outer<T> where T:StructOpt { + #[structopt(flatten)] + pub inner: T + } + + assert_eq!( + Outer{inner: Inner{ answer: 42 }}, + Outer::from_iter(&[ "--answer", "42" ]) + ) +} + +#[test] +fn generic_enum() { + + #[derive(StructOpt,PartialEq,Debug)] + struct Inner{ + pub answer: isize + } + + #[derive(StructOpt,PartialEq,Debug)] + enum GenericEnum<T: StructOpt> { + + Start(T), + Stop, + } + + assert_eq!( + GenericEnum::Start(Inner{answer: 42}), + GenericEnum::from_iter(&[ "test", "start", "42" ]) + ) + +} + +#[test] +fn generic_enum_w_where_clause() { + + #[derive(StructOpt,PartialEq,Debug)] + struct Inner{ + pub answer: isize + } + + #[derive(StructOpt,PartialEq,Debug)] + enum GenericEnum<T> where T: StructOpt { + + Start(T), + Stop, + } + + assert_eq!( + GenericEnum::Start(Inner{answer: 42}), + GenericEnum::from_iter(&[ "test", "start", "42" ]) + ) + +} + +#[test] +fn generic_w_fromstr_trait_bound() { + + use std::{fmt, str::FromStr}; + + #[derive(StructOpt,PartialEq,Debug)] + struct Opt<T> where T:FromStr, <T as FromStr>::Err: fmt::Debug + fmt::Display + { + answer: T + } + + assert_eq!( + Opt::<isize>{answer:42}, + Opt::<isize>::from_iter([& "--answer", "42" ]) + ) +} + +#[test] +fn generic_wo_trait_bound() { + + use std::time::Duration; + + #[derive(StructOpt,PartialEq,Debug)] + struct Opt<T> { + answer: isize, + #[structopt(skip)] + took: Option<T> + } + + assert_eq!( + Opt::<Duration>{answer:42,took:None}, + Opt::<Duration>::from_iter([& "--answer", "42" ]) + ) +} + +#[test] +fn generic_where_clause_w_trailing_comma() { + + use std::{fmt, str::FromStr}; + + #[derive(StructOpt,PartialEq,Debug)] + struct Opt<T> where T:FromStr, <T as FromStr>::Err: fmt::Debug + fmt::Display { + pub answer: T + } + + assert_eq!( + Opt::<isize>{answer:42}, + Opt::<isize>::from_iter(&[ "--answer", "42" ]) + ) +} |