eml_nl/utils/
authority_id.rs1use std::sync::LazyLock;
2
3use regex::Regex;
4use thiserror::Error;
5
6use crate::{EMLError, EMLValueResultExt, utils::StringValueData};
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10#[repr(transparent)]
11pub struct AuthorityId(String);
12
13impl AuthorityId {
14 pub fn new(s: impl AsRef<str>) -> Result<Self, EMLError> {
16 StringValueData::parse_from_str(s.as_ref()).wrap_value_error()
17 }
18
19 pub fn value(&self) -> &str {
21 &self.0
22 }
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Error)]
27#[repr(transparent)]
28#[error("Invalid authority id: {0}")]
29pub struct InvalidAuthorityIdError(String);
30
31static AUTHORITY_ID_RE: LazyLock<Regex> = LazyLock::new(|| {
33 Regex::new(r"^(CSB|((HSB|SB)\d+)|(\d{4}))$").expect("Failed to compile AuthorityId regex")
34});
35
36impl StringValueData for AuthorityId {
37 type Error = InvalidAuthorityIdError;
38
39 fn parse_from_str(s: &str) -> Result<Self, Self::Error>
40 where
41 Self: Sized,
42 {
43 if AUTHORITY_ID_RE.is_match(s) {
44 Ok(AuthorityId(s.to_string()))
45 } else {
46 Err(InvalidAuthorityIdError(s.to_string()))
47 }
48 }
49
50 fn to_raw_value(&self) -> String {
51 self.0.clone()
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn test_authority_id_regex_compiles() {
61 LazyLock::force(&AUTHORITY_ID_RE);
62 }
63
64 #[test]
65 fn test_authority_id_valid_values() {
66 let valid_values = [
67 "CSB", "HSB1", "HSB123", "SB10", "SB999", "0001", "1234", "9999",
68 ];
69
70 for value in valid_values {
71 let parsed = AuthorityId::parse_from_str(value);
72 assert!(
73 parsed.is_ok(),
74 "Expected '{}' to parse successfully, got error: {:?}",
75 value,
76 parsed.err()
77 );
78 }
79 }
80
81 #[test]
82 fn test_authority_id_invalid_values() {
83 let invalid_values = ["CS", "HSB", "SB", "123", "12345", "ABC", "SB-1"];
84 for value in invalid_values {
85 let parsed = AuthorityId::parse_from_str(value);
86 assert!(
87 parsed.is_err(),
88 "Expected '{}' to fail parsing, but got: {:?}",
89 value,
90 parsed.ok()
91 );
92 }
93 }
94}