Skip to main content

rfham_core/
id.rs

1//!
2//! Provides ..., a one-line description
3//!
4//! More detailed description
5//!
6//! # Examples
7//!
8//! ```rust
9//! ```
10//!
11
12use crate::error::CoreError as Error;
13use core::{fmt::Display, str::FromStr};
14use serde::{Deserialize, Serialize};
15
16// ------------------------------------------------------------------------------------------------
17// Public Macros
18// ------------------------------------------------------------------------------------------------
19
20#[macro_export]
21macro_rules! name_fn {
22    ($vis:vis $fn_name:ident => $name:literal) => {
23        #[inline(always)]
24        $vis fn $fn_name() -> $crate::id::Name {
25            $crate::id::Name::new_unchecked($name)
26        }
27    };
28}
29// ------------------------------------------------------------------------------------------------
30// Public Types
31// ------------------------------------------------------------------------------------------------
32
33#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
34pub struct Name(String);
35
36pub const RFHAM_URN_PREFIX: &str = "urn:rfham:";
37
38// ------------------------------------------------------------------------------------------------
39// Public Functions
40// ------------------------------------------------------------------------------------------------
41
42name_fn!(pub brand_name_baofeng =>  "baofeng");
43name_fn!(pub brand_name_chameleon =>  "chameleon");
44name_fn!(pub brand_name_elecraft =>  "elecraft");
45name_fn!(pub brand_name_gabil =>  "gabil");
46name_fn!(pub brand_name_icom =>  "icom");
47name_fn!(pub brand_name_kenwood =>  "kenwood");
48name_fn!(pub brand_name_yaesu => "yaesu");
49
50// ------------------------------------------------------------------------------------------------
51// Implementations
52// ------------------------------------------------------------------------------------------------
53
54impl Display for Name {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        write!(f, "{}", self.0)
57    }
58}
59
60impl From<Name> for String {
61    fn from(value: Name) -> Self {
62        value.0
63    }
64}
65
66impl AsRef<str> for Name {
67    fn as_ref(&self) -> &str {
68        self.0.as_ref()
69    }
70}
71
72impl FromStr for Name {
73    type Err = Error;
74
75    fn from_str(s: &str) -> Result<Self, Self::Err> {
76        if Self::is_valid(s) {
77            Ok(Self(s.to_ascii_lowercase()))
78        } else {
79            Err(Error::InvalidValueFromStr(s.to_string(), "Name"))
80        }
81    }
82}
83
84impl Name {
85    pub fn new_unchecked<S: Into<String>>(name: S) -> Self {
86        Self(name.into())
87    }
88
89    pub const fn as_str(&self) -> &str {
90        self.0.as_str()
91    }
92
93    pub fn is_valid(s: &str) -> bool {
94        let mut chars = s.chars();
95        !s.is_empty()
96            && chars.next().unwrap().is_ascii_alphabetic()
97            && chars.all(|c| c.is_ascii_alphanumeric() || ['-', '_'].contains(&c))
98    }
99}