From 68e74bc0589439ce307c3bad601e3d51a9475eee Mon Sep 17 00:00:00 2001 From: ChanTsune <41658782+ChanTsune@users.noreply.github.com> Date: Mon, 7 Aug 2023 23:54:55 +0900 Subject: [PATCH] Performance improvement eliminate `String` creation by utilizing the original &str slice --- src/parse.rs | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/parse.rs b/src/parse.rs index e86034e..a5cca5b 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -7,16 +7,12 @@ impl std::str::FromStr for ByteSize { if let Ok(v) = value.parse::() { return Ok(Self(v)); } - let number: String = value - .chars() - .take_while(|c| c.is_ascii_digit() || c == &'.') - .collect(); + let number = take_while(value, |c| c.is_ascii_digit() || c == '.'); match number.parse::() { Ok(v) => { - let suffix: String = value - .chars() - .skip_while(|c| c.is_whitespace() || c.is_ascii_digit() || c == &'.') - .collect(); + let suffix = skip_while(value, |c| { + c.is_whitespace() || c.is_ascii_digit() || c == '.' + }); match suffix.parse::() { Ok(u) => Ok(Self((v * u) as u64)), Err(error) => Err(format!( @@ -33,6 +29,30 @@ impl std::str::FromStr for ByteSize { } } +fn take_while

(s: &str, mut predicate: P) -> &str +where + P: FnMut(char) -> bool, +{ + let offset = s + .chars() + .take_while(|ch| predicate(*ch)) + .map(|ch| ch.len_utf8()) + .sum(); + &s[..offset] +} + +fn skip_while

(s: &str, mut predicate: P) -> &str +where + P: FnMut(char) -> bool, +{ + let offset: usize = s + .chars() + .skip_while(|ch| predicate(*ch)) + .map(|ch| ch.len_utf8()) + .sum(); + &s[(s.len() - offset)..] +} + enum Unit { Byte, // power of tens