about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-08-25 15:40:17 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-08-25 15:40:17 +0200
commit8327e89e0b66a6c43d14b8c3003e781635f9baa1 (patch)
tree3a3f995a1302ae335a7da628aac88b2485712a12
parentbuild(treewide): Update (diff)
downloadyt-8327e89e0b66a6c43d14b8c3003e781635f9baa1.tar.gz
yt-8327e89e0b66a6c43d14b8c3003e781635f9baa1.zip
feat(crates/bytes): Support decimal number input
-rw-r--r--crates/bytes/src/lib.rs46
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();