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