~goorzhel/sota-slack-spotter

ref: cf0e603ea8b53f26db74d4b2ba86173fe52e5a54 sota-slack-spotter/src/sota/mod.rs -rw-r--r-- 1.7 KiB
cf0e603e — Antonio Gurgel Add serde_with 4 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
pub mod alert;
pub mod spot;

use std::{fmt::Display, hash::Hash, str::FromStr};

use serde::{de::DeserializeOwned, Deserialize, Serialize};

use crate::callsign::{Callsign, Callsigns};

pub use self::{alert::all_alerts, spot::all_spots};

/// A spot or alert.
pub trait SOTAItem: Hash + Eq + DeserializeOwned + Serialize {
    fn callsign(&self) -> &Callsign;
    fn format_timestamp(&self) -> String;
    fn is_too_old(&self) -> bool;
    fn is_relevant(&self, callsigns: &Callsigns) -> bool {
        let base_callsign = self.callsign().strip().unwrap_or_else(|| "".into());
        callsigns.contains(&base_callsign) && !self.is_too_old()
    }
}

#[allow(clippy::upper_case_acronyms)]
#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)]
pub enum Mode {
    AM,
    CW,
    Data,
    DV,
    FM,
    SSB,
    Other,
}

// https://github.com/serde-rs/serde/issues/908#issuecomment-298027413
// Importing `serde_with` would mean another twenty crates.
impl<'de> Deserialize<'de> for Mode {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        FromStr::from_str(&s).map_err(serde::de::Error::custom)
    }
}

impl FromStr for Mode {
    type Err = anyhow::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mode = match s.to_lowercase().as_ref() {
            "am" => Mode::AM,
            "cw" => Mode::CW,
            "data" => Mode::Data,
            "dv" => Mode::DV,
            "fm" => Mode::FM,
            "ssb" => Mode::SSB,
            _ => Mode::Other,
        };
        Ok(mode)
    }
}

impl Display for Mode {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", self)
    }
}