use std::fmt::Display;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
#[serde(from = "String")]
pub struct Callsign(String);
impl From<&str> for Callsign {
fn from(s: &str) -> Self {
Self(s.trim().to_uppercase())
}
}
impl From<String> for Callsign {
fn from(s: String) -> Self {
Self::from(s.as_str())
}
}
impl Display for Callsign {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl Callsign {
pub fn strip(&self) -> Option<Callsign> {
let callsign = match self.0.matches('/').count() {
0 => &self.0,
1 => {
self.0
.split('/')
.reduce(|longest, cursor| {
if longest.len() < cursor.len() {
cursor
} else {
longest
}
})
.unwrap()
}
2 => {
self.0.split('/').nth(1).unwrap()
}
_ => {
return None; }
};
Some(callsign.into())
}
}
#[cfg(test)]
mod test {
use crate::Callsign;
#[test]
fn to_and_from_str() {
assert_eq!(
format!("{}", Callsign::from(String::from("n6tno"))),
"N6TNO"
);
}
#[test]
fn strip() {
let n6tno = Callsign::from("N6TNO");
assert_eq!(n6tno.strip().unwrap(), n6tno);
assert_eq!(Callsign::from("N6TNO/P").strip().unwrap(), n6tno);
assert_eq!(Callsign::from("PY2/N6TNO/P").strip().unwrap(), n6tno);
assert_eq!(Callsign::from("PY2/N6TNO/P/QRP").strip(), None);
}
}