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
This commit is contained in:
Kevin K 2015-04-23 16:58:30 -04:00
parent 258c97867d
commit fd61615d1a
4 changed files with 31 additions and 30 deletions

View file

@ -41,6 +41,7 @@ use args::{ FlagBuilder, OptBuilder, PosBuilder};
pub struct App<'a, 'v, 'ab, 'u, 'h, 'ar> {
// The name displayed to the user when showing version and help/usage information
name: String,
name_slice: &'ar str,
// A string of author(s) if desired. Displayed when showing help/usage information
author: Option<&'a str>,
// The version displayed to the user
@ -86,9 +87,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
/// let prog = App::new("myprog")
/// # .get_matches();
/// ```
pub fn new<'n>(n: &'n str) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
pub fn new(n: &'ar str) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
App {
name: n.to_owned(),
name_slice: n,
author: None,
about: None,
more_help: None,
@ -725,7 +727,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
}
// Used when spacing arguments and their help message when displaying help information
#[inline(always)]
fn get_spaces(&self, num: usize) -> &'static str {
match num {
0 => "",
@ -785,7 +786,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
// Starts the parsing process. Called on top level parent app **ONLY** then recursively calls
// the real parsing function for subcommands
pub fn get_matches(mut self) -> ArgMatches<'ar> {
pub fn get_matches(mut self) -> ArgMatches<'ar, 'ar> {
self.verify_positionals();
for (_,sc) in self.subcommands.iter_mut() {
sc.verify_positionals();
@ -844,7 +845,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
}
}
fn get_matches_from(&mut self, matches: &mut ArgMatches<'ar>, it: &mut IntoIter<String>) {
fn get_matches_from(&mut self, matches: &mut ArgMatches<'ar, 'ar>, it: &mut IntoIter<String>) {
self.create_help_and_version();
let mut pos_only = false;
@ -951,7 +952,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
// Was an update made, or is this the first occurrence?
if !done {
matches.args.insert(p.name, MatchedArg{
name: p.name.to_owned(),
// name: p.name.to_owned(),
occurrences: 1,
values: Some(vec![arg.clone()]),
});
@ -1008,7 +1009,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
sc.bin_name = Some(format!("{}{}{}", self.bin_name.clone().unwrap_or("".to_owned()),if self.bin_name.is_some() {" "} else {""}, sc.name.clone()));
sc.get_matches_from(&mut new_matches, it);
matches.subcommand = Some(Box::new(SubCommand{
name: sc.name.clone(),
name: sc.name_slice,
matches: new_matches}));
}
}
@ -1060,7 +1061,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
}
}
fn parse_long_arg(&mut self, matches: &mut ArgMatches<'ar> ,full_arg: &String) -> Option<&'ar str> {
fn parse_long_arg(&mut self, matches: &mut ArgMatches<'ar, 'ar> ,full_arg: &String) -> Option<&'ar str> {
let mut arg = full_arg.trim_left_matches(|c| c == '-');
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>{
}
} else {
matches.args.insert(v.name, MatchedArg{
name: v.name.to_owned(),
// name: v.name.to_owned(),
occurrences: if arg_val.is_some() { 1 } else { 0 },
values: if arg_val.is_some() { Some(vec![arg_val.clone().unwrap()])} else { Some(vec![]) }
});
@ -1167,7 +1168,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
}
if !done {
matches.args.insert(v.name, MatchedArg{
name: v.name.to_owned(),
// name: v.name.to_owned(),
occurrences: 1,
values: None
});
@ -1203,7 +1204,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
unreachable!();
}
fn parse_short_arg(&mut self, matches: &mut ArgMatches<'ar> ,full_arg: &String) -> Option<&'ar str> {
fn parse_short_arg(&mut self, matches: &mut ArgMatches<'ar, 'ar> ,full_arg: &String) -> Option<&'ar str> {
let arg = &full_arg[..].trim_left_matches(|c| c == '-');
if arg.len() > 1 {
// 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>{
}
} else {
matches.args.insert(v.name, MatchedArg{
name: v.name.to_owned(),
// name: v.name.to_owned(),
// occurrences will be incremented on getting a value
occurrences: 0,
values: Some(vec![])
@ -1273,7 +1274,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
unreachable!();
}
fn parse_single_short_flag(&mut self, matches: &mut ArgMatches<'ar>, arg: char) -> bool {
fn parse_single_short_flag(&mut self, matches: &mut ArgMatches<'ar, 'ar>, arg: char) -> bool {
for v in self.flags.values().filter(|&v| v.short.is_some()).filter(|&v| v.short.unwrap() == arg) {
// Ensure this flag isn't on the mutually excludes list
if self.blacklist.contains(v.name) {
@ -1293,7 +1294,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
}
if !done {
matches.args.insert(v.name, MatchedArg{
name: v.name.to_owned(),
// name: v.name.to_owned(),
occurrences: 1,
values: None
});
@ -1325,7 +1326,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
false
}
fn validate_blacklist(&self, matches: &ArgMatches<'ar>) {
fn validate_blacklist(&self, matches: &ArgMatches<'ar, 'ar>) {
for name in self.blacklist.iter() {
if matches.args.contains_key(name) {
self.report_error(format!("The argument {} cannot be used with one or more of the other specified arguments",

View file

@ -52,16 +52,16 @@ use args::MatchedArg;
/// println!("Not printing testing lists...");
/// }
/// }
pub struct ArgMatches<'a> {
pub struct ArgMatches<'n, 'a> {
#[doc(hidden)]
pub args: HashMap<&'a str, MatchedArg>,
#[doc(hidden)]
pub subcommand: Option<Box<SubCommand<'a>>>,
pub subcommand: Option<Box<SubCommand<'n, 'a>>>,
#[doc(hidden)]
pub usage: Option<String>
}
impl<'a> ArgMatches<'a> {
impl<'n, 'a> ArgMatches<'n, 'a> {
/// Creates a new instance of `ArgMatches`. This ins't called directly, but
/// through the `.get_matches()` method of `App`
///
@ -72,7 +72,7 @@ impl<'a> ArgMatches<'a> {
/// let matches = App::new("myprog").get_matches();
/// ```
#[doc(hidden)]
pub fn new() -> ArgMatches<'a> {
pub fn new() -> ArgMatches<'n, 'a> {
ArgMatches {
args: HashMap::new(),
subcommand: None,
@ -96,7 +96,7 @@ impl<'a> ArgMatches<'a> {
/// println!("Value for output: {}", o);
/// }
/// ```
pub fn value_of<'n>(&self, name: &'n str) -> Option<&str> {
pub fn value_of<'na>(&self, name: &'na str) -> Option<&str> {
if let Some(ref arg) = self.args.get(name) {
if let Some(ref vals) = arg.values {
if let Some(ref val) = vals.iter().nth(0) {
@ -125,7 +125,7 @@ impl<'a> ArgMatches<'a> {
/// }
/// }
/// ```
pub fn values_of<'n>(&'a self, name: &'n str) -> Option<Vec<&'a str>> {
pub fn values_of<'na>(&'a self, name: &'na str) -> Option<Vec<&'a str>> {
if let Some(ref arg) = self.args.get(name) {
if let Some(ref vals) = arg.values {
return Some(vals.iter().map(|s| &s[..]).collect::<Vec<_>>());
@ -146,7 +146,7 @@ impl<'a> ArgMatches<'a> {
/// println!("The output argument was used!");
/// }
/// ```
pub fn is_present<'n>(&self, name: &'n str) -> bool {
pub fn is_present<'na>(&self, name: &'na str) -> bool {
if let Some(ref sc) = self.subcommand {
if sc.name == name { return true; }
}
@ -170,7 +170,7 @@ impl<'a> ArgMatches<'a> {
/// println!("Debug mode kind of on");
/// }
/// ```
pub fn occurrences_of<'n>(&self, name: &'n str) -> u8 {
pub fn occurrences_of<'na>(&self, name: &'na str) -> u8 {
if let Some(ref arg) = self.args.get(name) {
return arg.occurrences;
}
@ -190,7 +190,7 @@ impl<'a> ArgMatches<'a> {
/// // Use matches as normal
/// }
/// ```
pub fn subcommand_matches<'n>(&self, name: &'n str) -> Option<&ArgMatches> {
pub fn subcommand_matches<'na>(&self, name: &'na str) -> Option<&ArgMatches> {
if let Some( ref sc) = self.subcommand {
if sc.name != name { return None; }
return Some(&sc.matches);

View file

@ -1,7 +1,7 @@
#[doc(hidden)]
pub struct MatchedArg {
#[doc(hidden)]
pub name: String,
// #[doc(hidden)]
// pub name: String,
#[doc(hidden)]
pub occurrences: u8,
#[doc(hidden)]

View file

@ -20,12 +20,12 @@ use ArgMatches;
/// .help("The configuration file to use")
/// .index(1))
/// # ).get_matches();
pub struct SubCommand<'a> {
pub name: String,
pub matches: ArgMatches<'a>
pub struct SubCommand<'n, 'a> {
pub name: &'n str,
pub matches: ArgMatches<'n, 'a>
}
impl<'a> SubCommand<'a> {
impl<'n, 'a> SubCommand<'n, 'a> {
/// Creates a new instance of a subcommand requiring a name. Will be displayed
/// to the user when they print version or help and usage information.
///
@ -37,7 +37,7 @@ impl<'a> SubCommand<'a> {
/// SubCommand::new("config")
/// # ).get_matches();
/// ```
pub fn new<'n, 'au, 'v, 'ab, 'u, 'h, 'ar>(name: &'n str) -> App<'au, 'v, 'ab, 'u, 'h, 'ar> {
pub fn new<'au, 'v, 'ab, 'u, 'h, 'ar>(name: &'ar str) -> App<'au, 'v, 'ab, 'u, 'h, 'ar> {
App::new(name)
}
}