1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3
4use crate::error::ParsingError;
5
6#[derive(Default, PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Debug)]
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9pub enum SNR {
10 DbHz0,
12
13 DbHz12,
15
16 DbHz12_17,
18
19 DbHz18_23,
21
22 #[default]
24 DbHz24_29,
25
26 DbHz30_35,
28
29 DbHz36_41,
31
32 DbHz42_47,
34
35 DbHz48_53,
37
38 DbHz54,
40}
41
42impl std::fmt::LowerHex for SNR {
43 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
45 match self {
46 Self::DbHz0 => f.write_str("0"),
47 Self::DbHz12 => f.write_str("1"),
48 Self::DbHz12_17 => f.write_str("2"),
49 Self::DbHz18_23 => f.write_str("3"),
50 Self::DbHz24_29 => f.write_str("4"),
51 Self::DbHz30_35 => f.write_str("5"),
52 Self::DbHz36_41 => f.write_str("6"),
53 Self::DbHz42_47 => f.write_str("7"),
54 Self::DbHz48_53 => f.write_str("8"),
55 Self::DbHz54 => f.write_str("9"),
56 }
57 }
58}
59
60impl std::fmt::Display for SNR {
61 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
63 match self {
64 Self::DbHz0 => f.write_str("<< 12 dB"),
65 Self::DbHz12 => f.write_str("< 12 dB"),
66 Self::DbHz12_17 => f.write_str("[12, 17[ dB"),
67 Self::DbHz18_23 => f.write_str("[18, 23[ dB"),
68 Self::DbHz24_29 => f.write_str("[24, 29[ dB"),
69 Self::DbHz30_35 => f.write_str("[30, 35[ dB"),
70 Self::DbHz36_41 => f.write_str("[36, 41[ dB"),
71 Self::DbHz42_47 => f.write_str("[42, 47[ dB"),
72 Self::DbHz48_53 => f.write_str("[48, 53[ dB"),
73 Self::DbHz54 => f.write_str("> 54 dB"),
74 }
75 }
76}
77
78impl std::str::FromStr for SNR {
79 type Err = ParsingError;
80
81 fn from_str(code: &str) -> Result<Self, Self::Err> {
83 match code.trim() {
84 "0" => Ok(Self::DbHz0),
85 "1" => Ok(Self::DbHz12),
86 "2" => Ok(Self::DbHz12_17),
87 "3" => Ok(Self::DbHz18_23),
88 "4" => Ok(Self::DbHz24_29),
89 "5" => Ok(Self::DbHz30_35),
90 "6" => Ok(Self::DbHz36_41),
91 "7" => Ok(Self::DbHz42_47),
92 "8" => Ok(Self::DbHz48_53),
93 "9" => Ok(Self::DbHz54),
94 "bad" => Ok(Self::DbHz18_23),
95 "weak" => Ok(Self::DbHz24_29),
96 "strong" => Ok(Self::DbHz30_35),
97 "excellent" => Ok(Self::DbHz48_53),
98 _ => Err(ParsingError::SNR),
99 }
100 }
101}
102
103impl From<f64> for SNR {
104 fn from(f_db: f64) -> Self {
105 if f_db < 12.0 {
106 Self::DbHz12
107 } else if f_db <= 17.0 {
108 Self::DbHz12_17
109 } else if f_db <= 23.0 {
110 Self::DbHz18_23
111 } else if f_db <= 29.0 {
112 Self::DbHz24_29
113 } else if f_db <= 35.0 {
114 Self::DbHz30_35
115 } else if f_db <= 41.0 {
116 Self::DbHz36_41
117 } else if f_db <= 47.0 {
118 Self::DbHz42_47
119 } else if f_db <= 53.0 {
120 Self::DbHz48_53
121 } else {
122 Self::DbHz54
123 }
124 }
125}
126
127impl From<SNR> for f64 {
128 fn from(val: SNR) -> Self {
129 match val {
130 SNR::DbHz0 => 0.0_f64,
131 SNR::DbHz12 => 12.0_f64,
132 SNR::DbHz12_17 => 17.0_f64,
133 SNR::DbHz18_23 => 23.0_f64,
134 SNR::DbHz24_29 => 29.0_f64,
135 SNR::DbHz30_35 => 35.0_f64,
136 SNR::DbHz36_41 => 41.0_f64,
137 SNR::DbHz42_47 => 47.0_f64,
138 SNR::DbHz48_53 => 53.0_f64,
139 SNR::DbHz54 => 54.0_f64,
140 }
141 }
142}
143
144impl From<u8> for SNR {
145 fn from(u: u8) -> Self {
146 match u {
147 1 => Self::DbHz12,
148 2 => Self::DbHz12_17,
149 3 => Self::DbHz18_23,
150 4 => Self::DbHz24_29,
151 5 => Self::DbHz30_35,
152 6 => Self::DbHz36_41,
153 7 => Self::DbHz42_47,
154 8 => Self::DbHz48_53,
155 9 => Self::DbHz54,
156 _ => Self::DbHz0,
157 }
158 }
159}
160
161impl SNR {
162 pub fn bad(self) -> bool {
164 self <= Self::DbHz18_23
165 }
166
167 pub fn weak(self) -> bool {
169 self < Self::DbHz30_35
170 }
171
172 pub fn strong(self) -> bool {
174 self >= Self::DbHz30_35
175 }
176
177 pub fn excellent(self) -> bool {
179 self > Self::DbHz42_47
180 }
181}
182
183#[cfg(test)]
184mod test {
185 use super::*;
186 use std::str::FromStr;
187
188 #[test]
189 fn snr_parsing() {
190 for (value, expected) in [("0", SNR::DbHz0), ("8", SNR::DbHz48_53), ("9", SNR::DbHz54)] {
191 let parsed = SNR::from_str(value).unwrap_or_else(|e| {
192 panic!("Failed to parse SNR from \"{}\"", value);
193 });
194
195 let formatted = format!("{:x}", parsed);
196
197 assert_eq!(formatted, value);
198 }
199
200 assert!(SNR::DbHz0.bad());
201 assert!(SNR::DbHz12.weak());
202 assert!(SNR::DbHz30_35.strong());
203 assert!(SNR::DbHz54.excellent());
204 }
205}