From 8327e89e0b66a6c43d14b8c3003e781635f9baa1 Mon Sep 17 00:00:00 2001 From: Benedikt Peetz Date: Sun, 25 Aug 2024 15:40:17 +0200 Subject: feat(crates/bytes): Support decimal number input --- crates/bytes/src/lib.rs | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) (limited to 'crates/bytes/src') diff --git a/crates/bytes/src/lib.rs b/crates/bytes/src/lib.rs index 9814a4a..113e8d5 100644 --- a/crates/bytes/src/lib.rs +++ b/crates/bytes/src/lib.rs @@ -45,16 +45,32 @@ impl FromStr for Bytes { type Err = BytesError; fn from_str(s: &str) -> Result { - let s = s - .chars() - .filter(|elem| !elem.is_whitespace()) - .collect::(); - - let number: u64 = s - .chars() - .take_while(|x| x.is_numeric()) - .collect::() - .parse()?; + let s = s.chars().filter(|s| !s.is_whitespace()).collect::(); + + let (whole_number, s): (u64, &str) = { + let number = s.chars().take_while(|x| x.is_numeric()).collect::(); + + (number.parse()?, &s[number.len()..]) + }; + + let (decimal_number, s, raise_factor) = { + if s.starts_with('.') { + let s_str = s + .chars() + .skip(1) // the decimal point + .take_while(|x| x.is_numeric()) + .collect::(); + + let s_num = s_str.parse::()?; + + (s_num, &s[s_str.len()..], s_str.len() as u32) + } else { + (0u64, s, 0) + } + }; + + let number = (whole_number * (10u64.pow(raise_factor))) + decimal_number; + let extension = s.chars().skip_while(|x| x.is_numeric()).collect::(); let output = match extension.to_lowercase().as_str() { @@ -71,7 +87,7 @@ impl FromStr for Bytes { other => return Err(BytesError::NotYetSupported(other.to_owned())), }; - Ok(Self(output)) + Ok(Self(output / (10u64.pow(raise_factor)))) } } @@ -147,6 +163,14 @@ mod tests { assert_eq!(expected, input.0); } + #[test] + fn parsing_not_round() { + let input: Bytes = "2.34 GiB".parse().unwrap(); + let expected = "2.34 GiB"; + + assert_eq!(expected, input.to_string().as_str()); + } + #[test] fn round_trip_1kib() { let input = "1 KiB"; -- cgit 1.4.1