1use credential_exchange_format::{
2 AddressCredential, DriversLicenseCredential, EditableField, EditableFieldString,
3 IdentityDocumentCredential, PassportCredential, PersonNameCredential,
4};
5
6use crate::{cxf::editable_field::create_field, Field, Identity};
7
8pub(super) fn address_to_identity(address: AddressCredential) -> (Identity, Vec<Field>) {
17 let identity = Identity {
18 address1: address.street_address.map(Into::into),
19 city: address.city.map(Into::into),
20 state: address.territory.map(Into::into),
21 postal_code: address.postal_code.map(Into::into),
22 country: address.country.map(Into::into),
23 phone: address.tel.map(Into::into),
24 ..Default::default()
25 };
26
27 (identity, vec![])
28}
29
30pub(super) fn passport_to_identity(passport: PassportCredential) -> (Identity, Vec<Field>) {
37 let (first_name, last_name) = split_name(&passport.full_name);
39
40 let identity = Identity {
41 first_name,
42 last_name,
43 ssn: passport.national_identification_number.map(Into::into),
45 passport_number: passport.passport_number.map(Into::into),
46 ..Default::default()
47 };
48
49 let custom_fields = [
51 passport
52 .issuing_country
53 .map(|issuing_country| create_field("Issuing Country", &issuing_country)),
54 passport
55 .nationality
56 .map(|nationality| create_field("Nationality", &nationality)),
57 passport
58 .birth_date
59 .map(|birth_date| create_field("Birth Date", &birth_date)),
60 passport
61 .birth_place
62 .map(|birth_place| create_field("Birth Place", &birth_place)),
63 passport.sex.map(|sex| create_field("Sex", &sex)),
64 passport
65 .issue_date
66 .map(|issue_date| create_field("Issue Date", &issue_date)),
67 passport
68 .expiry_date
69 .map(|expiry_date| create_field("Expiry Date", &expiry_date)),
70 passport
71 .issuing_authority
72 .map(|issuing_authority| create_field("Issuing Authority", &issuing_authority)),
73 passport
74 .passport_type
75 .map(|passport_type| create_field("Passport Type", &passport_type)),
76 ]
77 .into_iter()
78 .flatten()
79 .collect();
80
81 (identity, custom_fields)
82}
83
84pub(super) fn person_name_to_identity(person_name: PersonNameCredential) -> (Identity, Vec<Field>) {
94 let last_name = [
96 person_name.surname_prefix.as_ref(),
97 person_name.surname.as_ref(),
98 person_name.surname2.as_ref(),
99 ]
100 .into_iter()
101 .flatten()
102 .map(|field| field.value.0.clone())
103 .collect::<Vec<_>>()
104 .into_iter()
105 .reduce(|acc, part| format!("{acc} {part}"));
106
107 let identity = Identity {
108 title: person_name.title.map(Into::into),
109 first_name: person_name.given.map(Into::into),
110 middle_name: person_name.given2.map(Into::into),
111 last_name,
112 company: person_name.credentials.map(Into::into),
114 ..Default::default()
115 };
116
117 let custom_fields = [
119 person_name
120 .given_informal
121 .map(|given_informal| create_field("Informal Given Name", &given_informal)),
122 person_name
123 .generation
124 .map(|generation| create_field("Generation", &generation)),
125 ]
126 .into_iter()
127 .flatten()
128 .collect();
129
130 (identity, custom_fields)
131}
132
133pub(super) fn drivers_license_to_identity(
141 drivers_license: DriversLicenseCredential,
142) -> (Identity, Vec<Field>) {
143 let (first_name, last_name) = split_name(&drivers_license.full_name);
145
146 let identity = Identity {
147 first_name,
148 last_name,
149 state: drivers_license.territory.map(Into::into),
151 country: drivers_license.country.map(Into::into),
153 license_number: drivers_license.license_number.map(Into::into),
154 ..Default::default()
155 };
156
157 let custom_fields = [
159 drivers_license
160 .birth_date
161 .map(|birth_date| create_field("Birth Date", &birth_date)),
162 drivers_license
163 .issue_date
164 .map(|issue_date| create_field("Issue Date", &issue_date)),
165 drivers_license
166 .expiry_date
167 .map(|expiry_date| create_field("Expiry Date", &expiry_date)),
168 drivers_license
169 .issuing_authority
170 .map(|issuing_authority| create_field("Issuing Authority", &issuing_authority)),
171 drivers_license
172 .license_class
173 .map(|license_class| create_field("License Class", &license_class)),
174 ]
175 .into_iter()
176 .flatten()
177 .collect();
178
179 (identity, custom_fields)
180}
181
182pub(super) fn identity_document_to_identity(
191 identity_document: IdentityDocumentCredential,
192) -> (Identity, Vec<Field>) {
193 let (first_name, last_name) = split_name(&identity_document.full_name);
195
196 let identity = Identity {
197 first_name,
198 last_name,
199 ssn: identity_document.identification_number.map(Into::into),
201 passport_number: identity_document.document_number.map(Into::into),
203 ..Default::default()
204 };
205
206 let custom_fields = [
208 identity_document
209 .issuing_country
210 .map(|issuing_country| create_field("Issuing Country", &issuing_country)),
211 identity_document
212 .nationality
213 .map(|nationality| create_field("Nationality", &nationality)),
214 identity_document
215 .birth_date
216 .map(|birth_date| create_field("Birth Date", &birth_date)),
217 identity_document
218 .birth_place
219 .map(|birth_place| create_field("Birth Place", &birth_place)),
220 identity_document.sex.map(|sex| create_field("Sex", &sex)),
221 identity_document
222 .issue_date
223 .map(|issue_date| create_field("Issue Date", &issue_date)),
224 identity_document
225 .expiry_date
226 .map(|expiry_date| create_field("Expiry Date", &expiry_date)),
227 identity_document
228 .issuing_authority
229 .map(|issuing_authority| create_field("Issuing Authority", &issuing_authority)),
230 ]
231 .into_iter()
232 .flatten()
233 .collect();
234
235 (identity, custom_fields)
236}
237
238fn split_name(
239 full_name: &Option<EditableField<EditableFieldString>>,
240) -> (Option<String>, Option<String>) {
241 full_name.as_ref().map_or((None, None), |name| {
242 let parts: Vec<&str> = name.value.0.split_whitespace().collect();
243 match parts.as_slice() {
244 [] => (None, None),
245 [first] => (Some(first.to_string()), None),
246 [first, rest @ ..] => (Some(first.to_string()), Some(rest.join(" "))),
247 }
248 })
249}
250
251#[cfg(test)]
252mod tests {
253 use super::*;
254
255 #[test]
256 fn test_split_name_none() {
257 let full_name = None;
258 let (first, last) = split_name(&full_name);
259 assert_eq!(first, None);
260 assert_eq!(last, None);
261 }
262
263 #[test]
264 fn test_split_name_empty_string() {
265 let full_name = Some(EditableField {
266 value: EditableFieldString("".to_string()),
267 label: None,
268 id: None,
269 extensions: None,
270 });
271 let (first, last) = split_name(&full_name);
272 assert_eq!(first, None);
273 assert_eq!(last, None);
274 }
275
276 #[test]
277 fn test_split_name_whitespace_only() {
278 let full_name = Some(EditableField {
279 value: EditableFieldString(" \t\n ".to_string()),
280 label: None,
281 id: None,
282 extensions: None,
283 });
284 let (first, last) = split_name(&full_name);
285 assert_eq!(first, None);
286 assert_eq!(last, None);
287 }
288
289 #[test]
290 fn test_split_name_single_name() {
291 let full_name = Some(EditableField {
292 value: EditableFieldString("John".to_string()),
293 label: None,
294 id: None,
295 extensions: None,
296 });
297 let (first, last) = split_name(&full_name);
298 assert_eq!(first, Some("John".to_string()));
299 assert_eq!(last, None);
300 }
301
302 #[test]
303 fn test_split_name_single_name_with_whitespace() {
304 let full_name = Some(EditableField {
305 value: EditableFieldString(" John ".to_string()),
306 label: None,
307 id: None,
308 extensions: None,
309 });
310 let (first, last) = split_name(&full_name);
311 assert_eq!(first, Some("John".to_string()));
312 assert_eq!(last, None);
313 }
314
315 #[test]
316 fn test_split_name_first_last() {
317 let full_name = Some(EditableField {
318 value: EditableFieldString("John Doe".to_string()),
319 label: None,
320 id: None,
321 extensions: None,
322 });
323 let (first, last) = split_name(&full_name);
324 assert_eq!(first, Some("John".to_string()));
325 assert_eq!(last, Some("Doe".to_string()));
326 }
327
328 #[test]
329 fn test_split_name_first_middle_last() {
330 let full_name = Some(EditableField {
331 value: EditableFieldString("John Michael Doe".to_string()),
332 label: None,
333 id: None,
334 extensions: None,
335 });
336 let (first, last) = split_name(&full_name);
337 assert_eq!(first, Some("John".to_string()));
338 assert_eq!(last, Some("Michael Doe".to_string()));
339 }
340
341 #[test]
342 fn test_split_name_multiple_middle_names() {
343 let full_name = Some(EditableField {
344 value: EditableFieldString("John Michael Andrew Doe".to_string()),
345 label: None,
346 id: None,
347 extensions: None,
348 });
349 let (first, last) = split_name(&full_name);
350 assert_eq!(first, Some("John".to_string()));
351 assert_eq!(last, Some("Michael Andrew Doe".to_string()));
352 }
353
354 #[test]
355 fn test_split_name_complex_surname() {
356 let full_name = Some(EditableField {
357 value: EditableFieldString("Jane van der Berg".to_string()),
358 label: None,
359 id: None,
360 extensions: None,
361 });
362 let (first, last) = split_name(&full_name);
363 assert_eq!(first, Some("Jane".to_string()));
364 assert_eq!(last, Some("van der Berg".to_string()));
365 }
366
367 #[test]
368 fn test_split_name_hyphenated_surname() {
369 let full_name = Some(EditableField {
370 value: EditableFieldString("Mary Smith-Johnson".to_string()),
371 label: None,
372 id: None,
373 extensions: None,
374 });
375 let (first, last) = split_name(&full_name);
376 assert_eq!(first, Some("Mary".to_string()));
377 assert_eq!(last, Some("Smith-Johnson".to_string()));
378 }
379
380 #[test]
381 fn test_split_name_extra_whitespace() {
382 let full_name = Some(EditableField {
383 value: EditableFieldString(" John Michael Doe ".to_string()),
384 label: None,
385 id: None,
386 extensions: None,
387 });
388 let (first, last) = split_name(&full_name);
389 assert_eq!(first, Some("John".to_string()));
390 assert_eq!(last, Some("Michael Doe".to_string()));
391 }
392
393 #[test]
394 fn test_split_name_special_characters() {
395 let full_name = Some(EditableField {
396 value: EditableFieldString("José María González".to_string()),
397 label: None,
398 id: None,
399 extensions: None,
400 });
401 let (first, last) = split_name(&full_name);
402 assert_eq!(first, Some("José".to_string()));
403 assert_eq!(last, Some("María González".to_string()));
404 }
405
406 #[test]
407 fn test_split_name_single_character_names() {
408 let full_name = Some(EditableField {
409 value: EditableFieldString("A B C".to_string()),
410 label: None,
411 id: None,
412 extensions: None,
413 });
414 let (first, last) = split_name(&full_name);
415 assert_eq!(first, Some("A".to_string()));
416 assert_eq!(last, Some("B C".to_string()));
417 }
418}