bim_core/
utils.rs

1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5const WIDTH: [(u32, u8); 38] = [
6    (126, 1),
7    (159, 0),
8    (687, 1),
9    (710, 0),
10    (711, 1),
11    (727, 0),
12    (733, 1),
13    (879, 0),
14    (1154, 1),
15    (1161, 0),
16    (4347, 1),
17    (4447, 2),
18    (7467, 1),
19    (7521, 0),
20    (8369, 1),
21    (8426, 0),
22    (9000, 1),
23    (9002, 2),
24    (11021, 1),
25    (12350, 2),
26    (12351, 1),
27    (12438, 2),
28    (12442, 0),
29    (19893, 2),
30    (19967, 1),
31    (55203, 2),
32    (63743, 1),
33    (64106, 2),
34    (65039, 1),
35    (65059, 0),
36    (65131, 2),
37    (65279, 1),
38    (65376, 2),
39    (65500, 1),
40    (65510, 2),
41    (120831, 1),
42    (262141, 2),
43    (1114109, 1),
44];
45
46fn get_width(o: u32) -> u8 {
47    if o == 0xE || o == 0xF {
48        return 0;
49    }
50    for (num, wid) in WIDTH {
51        if o <= num {
52            return wid;
53        }
54    }
55    1
56}
57
58pub fn justify_name(name: &str, length: u8, left_right: bool) -> String {
59    let mut name_width = 0;
60    let mut justified_name = String::new();
61
62    for c in name.chars() {
63        let w = get_width(c as u32);
64        if name_width + w < length {
65            name_width += w;
66            justified_name.push(c);
67        }
68    }
69
70    if name_width < length {
71        let space_count = length - name_width;
72        let spaces = " ".repeat(space_count as usize);
73        if left_right {
74            justified_name += spaces.as_str();
75        } else {
76            justified_name = spaces + &justified_name;
77        }
78    }
79    justified_name
80}
81
82#[derive(Serialize, Deserialize)]
83pub struct SpeedTestResult {
84    #[serde(serialize_with = "serialize_f64")]
85    upload: f64,
86    upload_status: String,
87    #[serde(serialize_with = "serialize_f64")]
88    download: f64,
89    download_status: String,
90    #[serde(serialize_with = "serialize_f64")]
91    latency: f64,
92    #[serde(serialize_with = "serialize_f64")]
93    jitter: f64,
94}
95
96fn serialize_f64<S>(x: &f64, serializer: S) -> Result<S::Ok, S::Error>
97where
98    S: serde::Serializer,
99{
100    let s = format!("{:.1}", x);
101    serializer.serialize_str(&s)
102}
103
104impl SpeedTestResult {
105    pub fn build(
106        upload: f64,
107        upload_status: String,
108        download: f64,
109        download_status: String,
110        latency: f64,
111        jitter: f64,
112    ) -> SpeedTestResult {
113        return SpeedTestResult {
114            upload,
115            upload_status,
116            download,
117            download_status,
118            latency,
119            jitter,
120        };
121    }
122
123    pub fn text(&self) -> String {
124        let upload = justify_name(&format!("{:.1}", &self.upload), 9, false);
125        let upload_status = justify_name(&self.upload_status, 5, false);
126        let download = justify_name(&format!("{:.1}", &self.download), 9, false);
127        let download_status = justify_name(&self.download_status, 5, false);
128        let latency = justify_name(&format!("{:.1}", &self.latency), 7, false);
129        let jitter = justify_name(&format!("{:.1}", &self.jitter), 7, false);
130
131        format!("{upload},{upload_status},{download},{download_status},{latency},{jitter}")
132    }
133}
134
135impl fmt::Display for SpeedTestResult {
136    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137        write!(
138            f,
139            "Upload {:.1}Mbps {}, Download: {:.1}Mbps {}, Latency {:.1}, Jitter {:.1}",
140            self.upload,
141            self.upload_status,
142            self.download,
143            self.download_status,
144            self.latency,
145            self.jitter
146        )
147    }
148}