aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Galenson <jgalenson@google.com>2021-08-18 15:32:46 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-08-18 15:32:46 +0000
commitdd8566dc49af6a54030dfb7a98fe7f727fc5ace5 (patch)
tree09fa4d8ab7933bd6aea36bbcd7389cd71e2a373a
parent892dbbf7fa26c93d4ec6f852f0dd6c8f5026805a (diff)
parente18c60ecfa0a8bbe2e6371cf75ce0ed14e44bc03 (diff)
downloadstructopt-dd8566dc49af6a54030dfb7a98fe7f727fc5ace5.tar.gz
Upgrade rust/crates/structopt to 0.3.22 am: 108a00fc51 am: e3b7557ae7 am: e18c60ecfa
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/structopt/+/1791038 Change-Id: I035e110c5e192f7bdb5a5a2bcabbe58b8596edf5
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp14
-rw-r--r--CHANGELOG.md4
-rw-r--r--Cargo.toml8
-rw-r--r--Cargo.toml.orig5
-rw-r--r--METADATA10
-rw-r--r--examples/enum_in_args_with_strum.rs27
-rw-r--r--examples/example.rs2
-rw-r--r--src/lib.rs37
-rw-r--r--tests/generics.rs137
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"
}
}
diff --git a/Android.bp b/Android.bp
index 9905be3..3051273 100644
--- a/Android.bp
+++ b/Android.bp
@@ -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)
diff --git a/Cargo.toml b/Cargo.toml
index d24c98b..260ef4a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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"] }
diff --git a/METADATA b/METADATA
index df2195b..40329f0 100644
--- a/METADATA
+++ b/METADATA
@@ -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>>,
diff --git a/src/lib.rs b/src/lib.rs
index fb4ad85..b6e6b73 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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" ])
+ )
+}