Skip to content

Commit fd61615

Browse files
committed
perf(matchedargs): remove unused vars and String->&str
This commit increases the performance a bit by using string slices instead of owned strings. The trade off is that code previously written to handle all the argument parsing in a speratate function and return only the ArgMatches must be re-written to add a lifetime specifier: Old code 'fn handle_args<'a>() -> ArgMatches<'a>' needs another lifetime specifier added, so now 'fn handle_args<'a, 'b>() -> ArgMatches<'a, 'b>' BREAKING CHANGE
1 parent 258c978 commit fd61615

File tree

4 files changed

+31
-30
lines changed

4 files changed

+31
-30
lines changed

src/app.rs

+15-14
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ use args::{ FlagBuilder, OptBuilder, PosBuilder};
4141
pub struct App<'a, 'v, 'ab, 'u, 'h, 'ar> {
4242
// The name displayed to the user when showing version and help/usage information
4343
name: String,
44+
name_slice: &'ar str,
4445
// A string of author(s) if desired. Displayed when showing help/usage information
4546
author: Option<&'a str>,
4647
// The version displayed to the user
@@ -86,9 +87,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
8687
/// let prog = App::new("myprog")
8788
/// # .get_matches();
8889
/// ```
89-
pub fn new<'n>(n: &'n str) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
90+
pub fn new(n: &'ar str) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
9091
App {
9192
name: n.to_owned(),
93+
name_slice: n,
9294
author: None,
9395
about: None,
9496
more_help: None,
@@ -725,7 +727,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
725727
}
726728

727729
// Used when spacing arguments and their help message when displaying help information
728-
#[inline(always)]
729730
fn get_spaces(&self, num: usize) -> &'static str {
730731
match num {
731732
0 => "",
@@ -785,7 +786,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
785786

786787
// Starts the parsing process. Called on top level parent app **ONLY** then recursively calls
787788
// the real parsing function for subcommands
788-
pub fn get_matches(mut self) -> ArgMatches<'ar> {
789+
pub fn get_matches(mut self) -> ArgMatches<'ar, 'ar> {
789790
self.verify_positionals();
790791
for (_,sc) in self.subcommands.iter_mut() {
791792
sc.verify_positionals();
@@ -844,7 +845,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
844845
}
845846
}
846847

847-
fn get_matches_from(&mut self, matches: &mut ArgMatches<'ar>, it: &mut IntoIter<String>) {
848+
fn get_matches_from(&mut self, matches: &mut ArgMatches<'ar, 'ar>, it: &mut IntoIter<String>) {
848849
self.create_help_and_version();
849850

850851
let mut pos_only = false;
@@ -951,7 +952,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
951952
// Was an update made, or is this the first occurrence?
952953
if !done {
953954
matches.args.insert(p.name, MatchedArg{
954-
name: p.name.to_owned(),
955+
// name: p.name.to_owned(),
955956
occurrences: 1,
956957
values: Some(vec![arg.clone()]),
957958
});
@@ -1008,7 +1009,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
10081009
sc.bin_name = Some(format!("{}{}{}", self.bin_name.clone().unwrap_or("".to_owned()),if self.bin_name.is_some() {" "} else {""}, sc.name.clone()));
10091010
sc.get_matches_from(&mut new_matches, it);
10101011
matches.subcommand = Some(Box::new(SubCommand{
1011-
name: sc.name.clone(),
1012+
name: sc.name_slice,
10121013
matches: new_matches}));
10131014
}
10141015
}
@@ -1060,7 +1061,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
10601061
}
10611062
}
10621063

1063-
fn parse_long_arg(&mut self, matches: &mut ArgMatches<'ar> ,full_arg: &String) -> Option<&'ar str> {
1064+
fn parse_long_arg(&mut self, matches: &mut ArgMatches<'ar, 'ar> ,full_arg: &String) -> Option<&'ar str> {
10641065
let mut arg = full_arg.trim_left_matches(|c| c == '-');
10651066

10661067
if arg == "help" && self.needs_long_help {
@@ -1116,7 +1117,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
11161117
}
11171118
} else {
11181119
matches.args.insert(v.name, MatchedArg{
1119-
name: v.name.to_owned(),
1120+
// name: v.name.to_owned(),
11201121
occurrences: if arg_val.is_some() { 1 } else { 0 },
11211122
values: if arg_val.is_some() { Some(vec![arg_val.clone().unwrap()])} else { Some(vec![]) }
11221123
});
@@ -1167,7 +1168,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
11671168
}
11681169
if !done {
11691170
matches.args.insert(v.name, MatchedArg{
1170-
name: v.name.to_owned(),
1171+
// name: v.name.to_owned(),
11711172
occurrences: 1,
11721173
values: None
11731174
});
@@ -1203,7 +1204,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
12031204
unreachable!();
12041205
}
12051206

1206-
fn parse_short_arg(&mut self, matches: &mut ArgMatches<'ar> ,full_arg: &String) -> Option<&'ar str> {
1207+
fn parse_short_arg(&mut self, matches: &mut ArgMatches<'ar, 'ar> ,full_arg: &String) -> Option<&'ar str> {
12071208
let arg = &full_arg[..].trim_left_matches(|c| c == '-');
12081209
if arg.len() > 1 {
12091210
// Multiple flags using short i.e. -bgHlS
@@ -1239,7 +1240,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
12391240
}
12401241
} else {
12411242
matches.args.insert(v.name, MatchedArg{
1242-
name: v.name.to_owned(),
1243+
// name: v.name.to_owned(),
12431244
// occurrences will be incremented on getting a value
12441245
occurrences: 0,
12451246
values: Some(vec![])
@@ -1273,7 +1274,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
12731274
unreachable!();
12741275
}
12751276

1276-
fn parse_single_short_flag(&mut self, matches: &mut ArgMatches<'ar>, arg: char) -> bool {
1277+
fn parse_single_short_flag(&mut self, matches: &mut ArgMatches<'ar, 'ar>, arg: char) -> bool {
12771278
for v in self.flags.values().filter(|&v| v.short.is_some()).filter(|&v| v.short.unwrap() == arg) {
12781279
// Ensure this flag isn't on the mutually excludes list
12791280
if self.blacklist.contains(v.name) {
@@ -1293,7 +1294,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
12931294
}
12941295
if !done {
12951296
matches.args.insert(v.name, MatchedArg{
1296-
name: v.name.to_owned(),
1297+
// name: v.name.to_owned(),
12971298
occurrences: 1,
12981299
values: None
12991300
});
@@ -1325,7 +1326,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
13251326
false
13261327
}
13271328

1328-
fn validate_blacklist(&self, matches: &ArgMatches<'ar>) {
1329+
fn validate_blacklist(&self, matches: &ArgMatches<'ar, 'ar>) {
13291330
for name in self.blacklist.iter() {
13301331
if matches.args.contains_key(name) {
13311332
self.report_error(format!("The argument {} cannot be used with one or more of the other specified arguments",

src/args/argmatches.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,16 @@ use args::MatchedArg;
5252
/// println!("Not printing testing lists...");
5353
/// }
5454
/// }
55-
pub struct ArgMatches<'a> {
55+
pub struct ArgMatches<'n, 'a> {
5656
#[doc(hidden)]
5757
pub args: HashMap<&'a str, MatchedArg>,
5858
#[doc(hidden)]
59-
pub subcommand: Option<Box<SubCommand<'a>>>,
59+
pub subcommand: Option<Box<SubCommand<'n, 'a>>>,
6060
#[doc(hidden)]
6161
pub usage: Option<String>
6262
}
6363

64-
impl<'a> ArgMatches<'a> {
64+
impl<'n, 'a> ArgMatches<'n, 'a> {
6565
/// Creates a new instance of `ArgMatches`. This ins't called directly, but
6666
/// through the `.get_matches()` method of `App`
6767
///
@@ -72,7 +72,7 @@ impl<'a> ArgMatches<'a> {
7272
/// let matches = App::new("myprog").get_matches();
7373
/// ```
7474
#[doc(hidden)]
75-
pub fn new() -> ArgMatches<'a> {
75+
pub fn new() -> ArgMatches<'n, 'a> {
7676
ArgMatches {
7777
args: HashMap::new(),
7878
subcommand: None,
@@ -96,7 +96,7 @@ impl<'a> ArgMatches<'a> {
9696
/// println!("Value for output: {}", o);
9797
/// }
9898
/// ```
99-
pub fn value_of<'n>(&self, name: &'n str) -> Option<&str> {
99+
pub fn value_of<'na>(&self, name: &'na str) -> Option<&str> {
100100
if let Some(ref arg) = self.args.get(name) {
101101
if let Some(ref vals) = arg.values {
102102
if let Some(ref val) = vals.iter().nth(0) {
@@ -125,7 +125,7 @@ impl<'a> ArgMatches<'a> {
125125
/// }
126126
/// }
127127
/// ```
128-
pub fn values_of<'n>(&'a self, name: &'n str) -> Option<Vec<&'a str>> {
128+
pub fn values_of<'na>(&'a self, name: &'na str) -> Option<Vec<&'a str>> {
129129
if let Some(ref arg) = self.args.get(name) {
130130
if let Some(ref vals) = arg.values {
131131
return Some(vals.iter().map(|s| &s[..]).collect::<Vec<_>>());
@@ -146,7 +146,7 @@ impl<'a> ArgMatches<'a> {
146146
/// println!("The output argument was used!");
147147
/// }
148148
/// ```
149-
pub fn is_present<'n>(&self, name: &'n str) -> bool {
149+
pub fn is_present<'na>(&self, name: &'na str) -> bool {
150150
if let Some(ref sc) = self.subcommand {
151151
if sc.name == name { return true; }
152152
}
@@ -170,7 +170,7 @@ impl<'a> ArgMatches<'a> {
170170
/// println!("Debug mode kind of on");
171171
/// }
172172
/// ```
173-
pub fn occurrences_of<'n>(&self, name: &'n str) -> u8 {
173+
pub fn occurrences_of<'na>(&self, name: &'na str) -> u8 {
174174
if let Some(ref arg) = self.args.get(name) {
175175
return arg.occurrences;
176176
}
@@ -190,7 +190,7 @@ impl<'a> ArgMatches<'a> {
190190
/// // Use matches as normal
191191
/// }
192192
/// ```
193-
pub fn subcommand_matches<'n>(&self, name: &'n str) -> Option<&ArgMatches> {
193+
pub fn subcommand_matches<'na>(&self, name: &'na str) -> Option<&ArgMatches> {
194194
if let Some( ref sc) = self.subcommand {
195195
if sc.name != name { return None; }
196196
return Some(&sc.matches);

src/args/matchedarg.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#[doc(hidden)]
22
pub struct MatchedArg {
3-
#[doc(hidden)]
4-
pub name: String,
3+
// #[doc(hidden)]
4+
// pub name: String,
55
#[doc(hidden)]
66
pub occurrences: u8,
77
#[doc(hidden)]

src/args/subcommand.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ use ArgMatches;
2020
/// .help("The configuration file to use")
2121
/// .index(1))
2222
/// # ).get_matches();
23-
pub struct SubCommand<'a> {
24-
pub name: String,
25-
pub matches: ArgMatches<'a>
23+
pub struct SubCommand<'n, 'a> {
24+
pub name: &'n str,
25+
pub matches: ArgMatches<'n, 'a>
2626
}
2727

28-
impl<'a> SubCommand<'a> {
28+
impl<'n, 'a> SubCommand<'n, 'a> {
2929
/// Creates a new instance of a subcommand requiring a name. Will be displayed
3030
/// to the user when they print version or help and usage information.
3131
///
@@ -37,7 +37,7 @@ impl<'a> SubCommand<'a> {
3737
/// SubCommand::new("config")
3838
/// # ).get_matches();
3939
/// ```
40-
pub fn new<'n, 'au, 'v, 'ab, 'u, 'h, 'ar>(name: &'n str) -> App<'au, 'v, 'ab, 'u, 'h, 'ar> {
40+
pub fn new<'au, 'v, 'ab, 'u, 'h, 'ar>(name: &'ar str) -> App<'au, 'v, 'ab, 'u, 'h, 'ar> {
4141
App::new(name)
4242
}
4343
}

0 commit comments

Comments
 (0)