use strum_macros::{EnumMessage, EnumProperty};
#[derive(Debug, PartialEq, EnumMessage, EnumProperty)]
pub enum HKIDSymbol {
#[strum(props(Symbol = "***"), message = "The holder is aged 18 or over and eligible for a Hong Kong Re-entry Permit")]
AdultEligibleReentryPermit,
#[strum(props(Symbol = "*"), message = "The holder is aged between 11 and 17 and eligible for a Hong Kong Re-entry Permit")]
YouthEligibleReentryPermit,
#[strum(props(Symbol = "A"), message = "The holder has the right of abode in Hong Kong")]
RightOfAbode,
#[strum(props(Symbol = "B"), message = "The holder's reported date/place of birth has changed since first registration")]
BirthDateOrPlaceChanged,
#[strum(props(Symbol = "C"), message = "The holder's stay in Hong Kong is limited by the Director of Immigration at registration")]
StayLimitedByImmigration,
#[strum(props(Symbol = "N"), message = "The holder's reported name has changed since first registration")]
NameChanged,
#[strum(props(Symbol = "O"), message = "The holder was born outside Hong Kong, Mainland China, or Macau")]
BornOutsideHKChinaMacau,
#[strum(props(Symbol = "R"), message = "The holder has the right to land in Hong Kong")]
RightToLand,
#[strum(props(Symbol = "U"), message = "The holder's stay in Hong Kong is not limited by the Director of Immigration")]
StayUnlimitedByImmigration,
#[strum(props(Symbol = "W"), message = "The holder's reported place of birth is Macau")]
BornInMacau,
#[strum(props(Symbol = "X"), message = "The holder's reported place of birth is Mainland China")]
BornInMainlandChina,
#[strum(props(Symbol = "Y"), message = "The holder's date of birth has been confirmed by birth certificate or passport")]
BirthDateConfirmed,
#[strum(props(Symbol = "Z"), message = "The holder's reported place of birth is Hong Kong")]
BornInHongKong,
#[strum(props(Symbol = "<Office Code>"), message = "Issuing office code (e.g., H1, K2, S1, P1, V1, etc.)", )]
IssuingOfficeCode(String),
#[strum(props(Symbol = "<L#>"), message = "The holder has lost their ID card. 'L1' for once, 'L2' for twice, etc.")]
LostCard(u8),
#[strum(message = "Unknown or custom symbol", props(Symbol = "<Unknown>"))]
Unknown(String),
}
impl HKIDSymbol {
pub fn parse(symbol: &str) -> HKIDSymbol {
match symbol {
"***" => HKIDSymbol::AdultEligibleReentryPermit,
"*" => HKIDSymbol::YouthEligibleReentryPermit,
"A" => HKIDSymbol::RightOfAbode,
"B" => HKIDSymbol::BirthDateOrPlaceChanged,
"C" => HKIDSymbol::StayLimitedByImmigration,
"N" => HKIDSymbol::NameChanged,
"O" => HKIDSymbol::BornOutsideHKChinaMacau,
"R" => HKIDSymbol::RightToLand,
"U" => HKIDSymbol::StayUnlimitedByImmigration,
"W" => HKIDSymbol::BornInMacau,
"X" => HKIDSymbol::BornInMainlandChina,
"Y" => HKIDSymbol::BirthDateConfirmed,
"Z" => HKIDSymbol::BornInHongKong,
s if s.starts_with('L') && s.len() > 1 => {
if let Ok(times) = s[1..].parse::<u8>() {
HKIDSymbol::LostCard(times)
} else {
HKIDSymbol::Unknown(s.to_string())
}
}
s if s.len() == 2 && s.chars().nth(1).unwrap().is_ascii_digit() => {
HKIDSymbol::IssuingOfficeCode(s.to_string())
}
_ => HKIDSymbol::Unknown(symbol.to_string()),
}
}
}
#[cfg(test)]
mod tests {
use strum::EnumMessage;
use strum::EnumProperty;
use super::*;
#[test]
fn test_symbol_and_message_basic_variants() {
let symbol = HKIDSymbol::RightOfAbode;
assert_eq!(symbol.get_str("Symbol"), Some("A"));
assert_eq!(
symbol.get_message(),
Some("The holder has the right of abode in Hong Kong")
);
let symbol = HKIDSymbol::StayLimitedByImmigration;
assert_eq!(symbol.get_str("Symbol"), Some("C"));
assert_eq!(
symbol.get_message(),
Some("The holder's stay in Hong Kong is limited by the Director of Immigration at registration")
);
}
#[test]
fn test_symbol_and_message_lost_card() {
let symbol = HKIDSymbol::LostCard(2);
assert_eq!(symbol.get_str("Symbol"), Some("<L#>"));
assert_eq!(symbol.get_message(), Some("The holder has lost their ID card. 'L1' for once, 'L2' for twice, etc."));
}
#[test]
fn test_symbol_and_message_issuing_office_code() {
let symbol = HKIDSymbol::IssuingOfficeCode("K2".to_string());
assert_eq!(symbol.get_str("Symbol"), Some("<Office Code>"));
assert_eq!(symbol.get_message(), Some("Issuing office code (e.g., H1, K2, S1, P1, V1, etc.)"));
}
#[test]
fn test_symbol_and_message_unknown() {
let symbol = HKIDSymbol::Unknown("XYZ".to_string());
assert_eq!(symbol.get_str("Symbol"), Some("<Unknown>"));
assert_eq!(symbol.get_message(), Some("Unknown or custom symbol"));
}
#[test]
fn test_parse_standard_symbols() {
assert_eq!(HKIDSymbol::parse("***"), HKIDSymbol::AdultEligibleReentryPermit);
assert_eq!(HKIDSymbol::parse("*"), HKIDSymbol::YouthEligibleReentryPermit);
assert_eq!(HKIDSymbol::parse("A"), HKIDSymbol::RightOfAbode);
assert_eq!(HKIDSymbol::parse("B"), HKIDSymbol::BirthDateOrPlaceChanged);
assert_eq!(HKIDSymbol::parse("C"), HKIDSymbol::StayLimitedByImmigration);
assert_eq!(HKIDSymbol::parse("N"), HKIDSymbol::NameChanged);
assert_eq!(HKIDSymbol::parse("O"), HKIDSymbol::BornOutsideHKChinaMacau);
assert_eq!(HKIDSymbol::parse("R"), HKIDSymbol::RightToLand);
assert_eq!(HKIDSymbol::parse("U"), HKIDSymbol::StayUnlimitedByImmigration);
assert_eq!(HKIDSymbol::parse("W"), HKIDSymbol::BornInMacau);
assert_eq!(HKIDSymbol::parse("X"), HKIDSymbol::BornInMainlandChina);
assert_eq!(HKIDSymbol::parse("Y"), HKIDSymbol::BirthDateConfirmed);
assert_eq!(HKIDSymbol::parse("Z"), HKIDSymbol::BornInHongKong);
}
#[test]
fn test_parse_lost_card() {
assert_eq!(HKIDSymbol::parse("L1"), HKIDSymbol::LostCard(1));
assert_eq!(HKIDSymbol::parse("L2"), HKIDSymbol::LostCard(2));
assert_eq!(HKIDSymbol::parse("L10"), HKIDSymbol::LostCard(10));
assert_eq!(HKIDSymbol::parse("Lab"), HKIDSymbol::Unknown("Lab".to_string()));
}
#[test]
fn test_parse_issuing_office_code() {
assert_eq!(HKIDSymbol::parse("H1"), HKIDSymbol::IssuingOfficeCode("H1".to_string()));
assert_eq!(HKIDSymbol::parse("K2"), HKIDSymbol::IssuingOfficeCode("K2".to_string()));
assert_eq!(HKIDSymbol::parse("S9"), HKIDSymbol::IssuingOfficeCode("S9".to_string()));
assert_eq!(HKIDSymbol::parse("HF"), HKIDSymbol::Unknown("HF".to_string()));
}
#[test]
fn test_parse_unknown() {
assert_eq!(HKIDSymbol::parse("XYZ"), HKIDSymbol::Unknown("XYZ".to_string()));
assert_eq!(HKIDSymbol::parse(""), HKIDSymbol::Unknown("".to_string()));
assert_eq!(HKIDSymbol::parse("Q"), HKIDSymbol::Unknown("Q".to_string()));
assert_eq!(HKIDSymbol::parse("1"), HKIDSymbol::Unknown("1".to_string()));
}
}