k8s_metrics/
quantity.rs

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}