Skip to content

Commit

Permalink
Reduce code size of testing tokens if they're a number
Browse files Browse the repository at this point in the history
This commit is a tiny win in compiled code size of a final binary
including `clap` which shaves off 19k of compiled code locally.
Previously tokens were checked if they were a number by using
`.parse::<f64>().is_ok()`, but parsing floats is relatively heavyweight
in terms of code size. This replaces the check with a more naive "does
this string have lots of ascii digits" check where the compiled size of
this check should be much smaller.
  • Loading branch information
alexcrichton committed Oct 23, 2023
1 parent 1b84314 commit 9268629
Showing 1 changed file with 19 additions and 4 deletions.
23 changes: 19 additions & 4 deletions clap_lex/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,7 @@ impl<'s> ParsedArg<'s> {

/// Does the argument look like a number
pub fn is_number(&self) -> bool {
self.to_value()
.map(|s| s.parse::<f64>().is_ok())
.unwrap_or_default()
self.to_value().map(looks_like_number).unwrap_or_default()
}

/// Treat as a long-flag
Expand Down Expand Up @@ -409,7 +407,7 @@ impl<'s> ShortFlags<'s> {
///
/// Ideally call this before doing any iterator
pub fn is_number(&self) -> bool {
self.invalid_suffix.is_none() && self.utf8_prefix.as_str().parse::<f64>().is_ok()
self.invalid_suffix.is_none() && looks_like_number(self.utf8_prefix.as_str())
}

/// Advance the iterator, returning the next short flag on success
Expand Down Expand Up @@ -466,3 +464,20 @@ fn split_nonutf8_once(b: &OsStr) -> (&str, Option<&OsStr>) {
}
}
}

fn looks_like_number(arg: &str) -> bool {
// strip a leading `-` in case this is a negative number
let arg = arg.strip_prefix("-").unwrap_or(arg);

// Return true if this looks like an integer or a float where it's all
// digits plus an optional single dot after some digits.
let mut seen_dot = false;
for (i, c) in arg.as_bytes().iter().enumerate() {
match c {
b'0'..=b'9' => {}
b'.' if !seen_dot && i > 0 => seen_dot = true,
_ => return false,
}
}
true
}

0 comments on commit 9268629

Please sign in to comment.