use super::error::CountryCodeError;
pub(super) fn normalize(input: &str) -> Result<[u8; 2], CountryCodeError> {
if input.is_empty() {
return Err(CountryCodeError::Empty);
}
let trimmed = input.trim();
let found = trimmed.chars().count();
if found != 2 {
return Err(CountryCodeError::InvalidLength { found });
}
let mut buf = [0u8; 2];
for (i, ch) in trimmed.chars().enumerate() {
if !ch.is_ascii() {
return Err(CountryCodeError::InvalidCharacter {
character: ch,
position: (i + 1) as u8,
});
}
buf[i] = ch.to_ascii_uppercase() as u8;
}
Ok(buf)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rejects_empty() {
assert_eq!(normalize(""), Err(CountryCodeError::Empty));
}
#[test]
fn trims_surrounding_whitespace() {
assert_eq!(normalize(" US "), normalize("US"));
}
#[test]
fn uppercases_letters() {
assert_eq!(normalize("us").unwrap(), *b"US");
}
#[test]
fn rejects_wrong_length() {
assert_eq!(
normalize("USA"),
Err(CountryCodeError::InvalidLength { found: 3 })
);
}
#[test]
fn whitespace_only_is_a_length_error() {
assert_eq!(
normalize(" "),
Err(CountryCodeError::InvalidLength { found: 0 })
);
}
#[test]
fn keeps_non_letter_characters_for_validation() {
assert_eq!(normalize("U.").unwrap(), *b"U.");
}
#[test]
fn rejects_non_ascii() {
let err = normalize("U£").unwrap_err();
assert!(matches!(
err,
CountryCodeError::InvalidCharacter {
character: '£', ..
}
));
}
}