1use super::*;
2
3pub trait QuantityExt {
4 fn to_memory(&self) -> Result<i64, QuantityParseError>;
5 fn to_f64(&self) -> Result<f64, QuantityParseError>;
6}
7
8impl QuantityExt for resource::Quantity {
9 fn to_memory(&self) -> Result<i64, QuantityParseError> {
10 if let Some((number, _unit)) = self.0.split_once("Ki") {
11 number.parse::<i64>().map(|n| n * 1024)
12 } else if let Some((number, _unit)) = self.0.split_once("Mi") {
13 number.parse::<i64>().map(|n| n * 1024 * 1024)
14 } else if let Some((number, _unit)) = self.0.split_once("Gi") {
15 number.parse::<i64>().map(|n| n * 1024 * 1024 * 1024)
16 } else {
17 self.0.parse::<i64>()
18 }
19 .map_err(|_e| QuantityParseError::new(&self.0))
20 }
21
22 fn to_f64(&self) -> Result<f64, QuantityParseError> {
23 let out = if let Some((number, _unit)) = self.0.split_once('n') {
24 number.parse::<f64>().map(|f| f / 1_000_000_000_f64)
25 } else if let Some((number, _unit)) = self.0.split_once('u') {
26 number.parse::<f64>().map(|f| f / 1_000_000_f64)
27 } else if let Some((number, _unit)) = self.0.split_once('m') {
28 number.parse::<f64>().map(|f| f / 1_000_f64)
29 } else {
30 self.0.parse::<f64>()
31 };
32
33 out.map_err(|_e| QuantityParseError::new(&self.0))
34 }
35}
36
37#[derive(Debug, thiserror::Error)]
38#[error("Unexpected format: {0}")]
39pub struct QuantityParseError(String);
40
41impl QuantityParseError {
42 fn new(text: &str) -> Self {
43 Self(text.to_string())
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 #![allow(non_snake_case)]
50
51 use super::*;
52
53 #[test]
54 fn memory_Ki() {
55 let q = quantity("2Ki").to_memory().unwrap();
56 assert_eq!(q, 2048);
57 }
58
59 #[test]
60 fn memory_Mi() {
61 let q = quantity("5Mi").to_memory().unwrap();
62 assert_eq!(q, 5242880);
63 }
64
65 #[test]
66 fn memory_Gi() {
67 let q = quantity("3Gi").to_memory().unwrap();
68 assert_eq!(q, 3221225472);
69 }
70
71 #[test]
72 fn leading_zeros() {
73 let q = quantity("0004Ki").to_memory().unwrap();
74 assert_eq!(q, 4096);
75 }
76
77 #[test]
78 fn cpu_nano() {
79 let q = quantity("257n").to_f64().unwrap();
80 assert_eq!(q, 0.000000257);
81 }
82
83 #[test]
84 fn cpu_micro() {
85 let q = quantity("303u").to_f64().unwrap();
86 assert_eq!(q, 0.000303);
87 }
88
89 #[test]
90 fn cpu_milli() {
91 let q = quantity("3491m").to_f64().unwrap();
92 assert_eq!(q, 3.491);
93 }
94
95 fn quantity(v: &str) -> resource::Quantity {
96 resource::Quantity(v.to_string())
97 }
98}