use crate::{hkid_check_digit::calculate_check_digit, HKID_FULL_REGEX, hkid_prefix::HKIDPrefix};
pub fn validate_hkid(hkid_full: &str, must_exist_in_enum: bool) -> Result<bool, String> {
let cleaned = hkid_full.chars().filter(|&c| c != '(' && c != ')').collect::<String>();
let caps = HKID_FULL_REGEX.captures(&cleaned)
.ok_or_else(|| "Invalid HKID format: incorrect structure.".to_string())?;
let (_, [prefix, digits, provided_digit]) = caps.extract();
if must_exist_in_enum {
let parsed_prefix = HKIDPrefix::parse(prefix);
if !parsed_prefix.is_known() {
return Err(format!("Prefix '{prefix}' is not recognized."));
}
}
let hkid_body = format!("{prefix}{digits}");
let calculated_digit = calculate_check_digit(&hkid_body).ok_or_else(|| "Failed to calculate check digit".to_string())?;
let provided_digit = provided_digit.chars().next().ok_or_else(|| "Missing check digit".to_string())?;
Ok(calculated_digit == provided_digit)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validate_hkid_correct() {
let valid_hkid = "A123456(3)";
let result = validate_hkid(valid_hkid, false);
assert!(result.is_ok());
assert_eq!(result.unwrap(), true);
}
#[test]
fn test_validate_hkid_incorrect_digit() {
let invalid_hkid = "A123456(9)";
let result = validate_hkid(invalid_hkid, false);
assert!(result.is_ok());
assert_eq!(result.unwrap(), false);
}
#[test]
fn test_validate_hkid_invalid_format() {
let invalid_hkid_format = "A12345"; let result = validate_hkid(invalid_hkid_format, false);
assert!(result.is_err());
assert_eq!(
result.unwrap_err(),
"Invalid HKID format: incorrect structure."
);
}
#[test]
fn test_validate_hkid_missing_check_digit() {
let missing_digit = "A123456";
let result = validate_hkid(missing_digit, false);
assert!(result.is_err());
assert_eq!(
result.unwrap_err(),
"Invalid HKID format: incorrect structure."
);
}
#[test]
fn test_validate_hkid_unknown_prefix_with_must_exist() {
let hkid = "XX123456(1)";
let result = validate_hkid(hkid, true);
assert!(result.is_err());
assert_eq!(result.unwrap_err(), "Prefix 'XX' is not recognized.");
}
#[test]
fn test_validate_hkid_unknown_prefix_without_must_exist() {
let hkid = "ZZ123456(8)";
let result = validate_hkid(hkid, false);
assert!(result.is_ok());
}
#[test]
fn test_validate_hkid_no_parentheses() {
let valid_hkid = "A1234563";
let result = validate_hkid(valid_hkid, false);
assert!(result.is_ok());
assert_eq!(result.unwrap(), true);
}
}