#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::error::ParsingError;
#[derive(Default, PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum SNR {
DbHz0,
DbHz12,
DbHz12_17,
DbHz18_23,
#[default]
DbHz24_29,
DbHz30_35,
DbHz36_41,
DbHz42_47,
DbHz48_53,
DbHz54,
}
impl std::fmt::LowerHex for SNR {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::DbHz0 => f.write_str("0"),
Self::DbHz12 => f.write_str("1"),
Self::DbHz12_17 => f.write_str("2"),
Self::DbHz18_23 => f.write_str("3"),
Self::DbHz24_29 => f.write_str("4"),
Self::DbHz30_35 => f.write_str("5"),
Self::DbHz36_41 => f.write_str("6"),
Self::DbHz42_47 => f.write_str("7"),
Self::DbHz48_53 => f.write_str("8"),
Self::DbHz54 => f.write_str("9"),
}
}
}
impl std::fmt::Display for SNR {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::DbHz0 => f.write_str("<< 12 dB"),
Self::DbHz12 => f.write_str("< 12 dB"),
Self::DbHz12_17 => f.write_str("[12, 17[ dB"),
Self::DbHz18_23 => f.write_str("[18, 23[ dB"),
Self::DbHz24_29 => f.write_str("[24, 29[ dB"),
Self::DbHz30_35 => f.write_str("[30, 35[ dB"),
Self::DbHz36_41 => f.write_str("[36, 41[ dB"),
Self::DbHz42_47 => f.write_str("[42, 47[ dB"),
Self::DbHz48_53 => f.write_str("[48, 53[ dB"),
Self::DbHz54 => f.write_str("> 54 dB"),
}
}
}
impl std::str::FromStr for SNR {
type Err = ParsingError;
fn from_str(code: &str) -> Result<Self, Self::Err> {
match code.trim() {
"0" => Ok(Self::DbHz0),
"1" => Ok(Self::DbHz12),
"2" => Ok(Self::DbHz12_17),
"3" => Ok(Self::DbHz18_23),
"4" => Ok(Self::DbHz24_29),
"5" => Ok(Self::DbHz30_35),
"6" => Ok(Self::DbHz36_41),
"7" => Ok(Self::DbHz42_47),
"8" => Ok(Self::DbHz48_53),
"9" => Ok(Self::DbHz54),
"bad" => Ok(Self::DbHz18_23),
"weak" => Ok(Self::DbHz24_29),
"strong" => Ok(Self::DbHz30_35),
"excellent" => Ok(Self::DbHz48_53),
_ => Err(ParsingError::SNR),
}
}
}
impl From<f64> for SNR {
fn from(f_db: f64) -> Self {
if f_db < 12.0 {
Self::DbHz12
} else if f_db <= 17.0 {
Self::DbHz12_17
} else if f_db <= 23.0 {
Self::DbHz18_23
} else if f_db <= 29.0 {
Self::DbHz24_29
} else if f_db <= 35.0 {
Self::DbHz30_35
} else if f_db <= 41.0 {
Self::DbHz36_41
} else if f_db <= 47.0 {
Self::DbHz42_47
} else if f_db <= 53.0 {
Self::DbHz48_53
} else {
Self::DbHz54
}
}
}
impl From<SNR> for f64 {
fn from(val: SNR) -> Self {
match val {
SNR::DbHz0 => 0.0_f64,
SNR::DbHz12 => 12.0_f64,
SNR::DbHz12_17 => 17.0_f64,
SNR::DbHz18_23 => 23.0_f64,
SNR::DbHz24_29 => 29.0_f64,
SNR::DbHz30_35 => 35.0_f64,
SNR::DbHz36_41 => 41.0_f64,
SNR::DbHz42_47 => 47.0_f64,
SNR::DbHz48_53 => 53.0_f64,
SNR::DbHz54 => 54.0_f64,
}
}
}
impl From<u8> for SNR {
fn from(u: u8) -> Self {
match u {
1 => Self::DbHz12,
2 => Self::DbHz12_17,
3 => Self::DbHz18_23,
4 => Self::DbHz24_29,
5 => Self::DbHz30_35,
6 => Self::DbHz36_41,
7 => Self::DbHz42_47,
8 => Self::DbHz48_53,
9 => Self::DbHz54,
_ => Self::DbHz0,
}
}
}
impl SNR {
pub fn bad(self) -> bool {
self <= Self::DbHz18_23
}
pub fn weak(self) -> bool {
self < Self::DbHz30_35
}
pub fn strong(self) -> bool {
self >= Self::DbHz30_35
}
pub fn excellent(self) -> bool {
self > Self::DbHz42_47
}
}
#[cfg(test)]
mod test {
use super::*;
use std::str::FromStr;
#[test]
fn snr_parsing() {
for (value, expected) in [("0", SNR::DbHz0), ("8", SNR::DbHz48_53), ("9", SNR::DbHz54)] {
let parsed = SNR::from_str(value).unwrap_or_else(|e| {
panic!("Failed to parse SNR from \"{}\"", value);
});
let formatted = format!("{:x}", parsed);
assert_eq!(formatted, value);
}
assert!(SNR::DbHz0.bad());
assert!(SNR::DbHz12.weak());
assert!(SNR::DbHz30_35.strong());
assert!(SNR::DbHz54.excellent());
}
}