1use chrono::NaiveDate;
2use std::fmt;
3
4use crate::Sex;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct MRZResult {
10 pub document_type: String,
11 pub country_code: String,
12 pub surnames: String,
13 pub given_names: String,
14 pub document_number: String,
15 pub nationality_country_code: String,
16 pub birth_date: NaiveDate,
17 pub sex: Sex,
18 pub expiry_date: NaiveDate,
19 pub personal_number: String,
20 pub personal_number2: Option<String>,
21}
22
23impl MRZResult {
24 #[allow(clippy::too_many_arguments)]
32 pub fn new(
33 document_type: impl Into<String>,
34 country_code: impl Into<String>,
35 surnames: impl Into<String>,
36 given_names: impl Into<String>,
37 document_number: impl Into<String>,
38 nationality_country_code: impl Into<String>,
39 birth_date: NaiveDate,
40 sex: Sex,
41 expiry_date: NaiveDate,
42 personal_number: impl Into<String>,
43 personal_number2: Option<impl Into<String>>,
44 ) -> Self {
45 MRZResult {
46 document_type: document_type.into(),
47 country_code: country_code.into(),
48 surnames: surnames.into(),
49 given_names: given_names.into(),
50 document_number: document_number.into(),
51 nationality_country_code: nationality_country_code.into(),
52 birth_date,
53 sex,
54 expiry_date,
55 personal_number: personal_number.into(),
56 personal_number2: personal_number2.map(|s| s.into()),
57 }
58 }
59}
60
61impl fmt::Display for MRZResult {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 write!(
64 f,
65 "MRZResult {{ document_type: {}, country_code: {}, surnames: {}, given_names: {}, document_number: {}, nationality: {}, birth_date: {}, sex: {:?}, expiry_date: {}, personal_number: {}, personal_number2: {:?} }}",
66 self.document_type,
67 self.country_code,
68 self.surnames,
69 self.given_names,
70 self.document_number,
71 self.nationality_country_code,
72 self.birth_date,
73 self.sex,
74 self.expiry_date,
75 self.personal_number,
76 self.personal_number2,
77 )
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use crate::Sex;
85 use chrono::NaiveDate;
86
87 #[test]
88 fn create_and_compare_results() {
89 let birth = NaiveDate::from_ymd_opt(1990, 5, 20).expect("valid date");
90 let expiry = NaiveDate::from_ymd_opt(2030, 5, 20).expect("valid date");
91
92 let r1 = MRZResult::new(
93 "P",
94 "UTO",
95 "DOE",
96 "JOHN",
97 "123456789",
98 "UTO",
99 birth,
100 Sex::Male,
101 expiry,
102 "ABC123<<<",
103 Some("SECOND".to_string()),
104 );
105
106 let r2 = MRZResult {
107 document_type: "P".into(),
108 country_code: "UTO".into(),
109 surnames: "DOE".into(),
110 given_names: "JOHN".into(),
111 document_number: "123456789".into(),
112 nationality_country_code: "UTO".into(),
113 birth_date: birth,
114 sex: Sex::Male,
115 expiry_date: expiry,
116 personal_number: "ABC123<<<".into(),
117 personal_number2: Some("SECOND".into()),
118 };
119
120 assert_eq!(r1, r2);
121 assert!(r1.personal_number2.is_some());
122 }
123
124 #[test]
125 fn display_contains_key_fields() {
126 let birth = NaiveDate::from_ymd_opt(1985, 1, 1).unwrap();
127 let expiry = NaiveDate::from_ymd_opt(2025, 1, 1).unwrap();
128
129 let r = MRZResult::new(
130 "ID",
131 "GBR",
132 "SMITH",
133 "JANE",
134 "X9876543",
135 "GBR",
136 birth,
137 Sex::Female,
138 expiry,
139 "ZZZ000<<<",
140 None::<String>,
141 );
142
143 let s = format!("{}", r);
144 assert!(s.contains("SMITH"));
145 assert!(s.contains("JANE"));
146 assert!(s.contains("GBR"));
147 }
148}