use super::exceptions::MRZError;
use super::result::MRZResult;
pub struct MRZParser;
impl MRZParser {
pub fn try_parse(input: Option<Vec<Option<String>>>) -> Option<MRZResult> {
Self::parse(input).ok()
}
pub fn parse(input: Option<Vec<Option<String>>>) -> Result<MRZResult, MRZError> {
let polished = polish_input(input).ok_or_else(MRZError::invalid_mrz_input)?;
if super::td1_format_mrz_parser::is_valid_input(&polished) {
return super::td1_format_mrz_parser::parse(&polished);
}
if super::td2_format_mrz_parser::is_valid_input(&polished) {
return super::td2_format_mrz_parser::parse(&polished);
}
if super::td3_format_mrz_parser::is_valid_input(&polished) {
return super::td3_format_mrz_parser::parse(&polished);
}
Err(MRZError::invalid_mrz_input())
}
}
fn polish_input(input: Option<Vec<Option<String>>>) -> Option<Vec<String>> {
let lines = input?;
let polished: Vec<String> = lines
.into_iter()
.filter_map(|opt| opt.map(|s| s.to_ascii_uppercase()))
.collect();
if polished.is_empty() {
return None;
}
if polished
.iter()
.any(|line| !super::string_extensions::is_valid_mrz_input(line))
{
return None;
}
Some(polished)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn polish_input_filters_and_upcases() {
let input = Some(vec![
Some("p<uto123".to_string()),
None,
Some("abcdef".to_string()),
]);
let polished = polish_input(input).expect("should polish");
assert_eq!(polished.len(), 2);
assert_eq!(polished[0], "P<UTO123");
assert_eq!(polished[1], "ABCDEF");
}
#[test]
fn polish_input_rejects_invalid_chars() {
let input = Some(vec![
Some("valid<MRZ".to_string()),
Some("has space".to_string()),
]);
assert!(polish_input(input).is_none());
}
#[test]
fn try_parse_returns_none_on_invalid_input() {
assert!(MRZParser::try_parse(None).is_none());
let input = Some(vec![Some("HAS SPACE".to_string())]);
assert!(MRZParser::try_parse(input).is_none());
}
#[test]
fn parse_returns_invalid_error_on_bad_input() {
let err = MRZParser::parse(None).unwrap_err();
assert!(format!("{}", err).contains("Invalid MRZ parser input"));
}
}