diff options
Diffstat (limited to '')
-rw-r--r-- | crates/bytes/src/lib.rs | 46 |
1 files changed, 35 insertions, 11 deletions
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<Self, Self::Err> { - let s = s - .chars() - .filter(|elem| !elem.is_whitespace()) - .collect::<String>(); - - let number: u64 = s - .chars() - .take_while(|x| x.is_numeric()) - .collect::<String>() - .parse()?; + let s = s.chars().filter(|s| !s.is_whitespace()).collect::<String>(); + + let (whole_number, s): (u64, &str) = { + let number = s.chars().take_while(|x| x.is_numeric()).collect::<String>(); + + (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::<String>(); + + let s_num = s_str.parse::<u64>()?; + + (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::<String>(); 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)))) } } @@ -148,6 +164,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"; let parsed: Bytes = input.parse().unwrap(); |