1use credential_exchange_format::{
2 AddressCredential, Credential, CustomFieldsCredential, DriversLicenseCredential, EditableField,
3 EditableFieldString, EditableFieldValue, IdentityDocumentCredential, PassportCredential,
4 PersonNameCredential,
5};
6
7use crate::{
8 Field, Identity,
9 cxf::editable_field::{create_editable_field, create_field},
10};
11
12pub(super) fn address_to_identity(address: AddressCredential) -> (Identity, Vec<Field>) {
21 let identity = Identity {
22 address1: address.street_address.map(Into::into),
23 city: address.city.map(Into::into),
24 state: address.territory.map(Into::into),
25 postal_code: address.postal_code.map(Into::into),
26 country: address.country.map(Into::into),
27 phone: address.tel.map(Into::into),
28 ..Default::default()
29 };
30
31 (identity, vec![])
32}
33
34pub(super) fn passport_to_identity(passport: PassportCredential) -> (Identity, Vec<Field>) {
41 let (first_name, last_name) = split_name(&passport.full_name);
43
44 let identity = Identity {
45 first_name,
46 last_name,
47 ssn: passport.national_identification_number.map(Into::into),
49 passport_number: passport.passport_number.map(Into::into),
50 ..Default::default()
51 };
52
53 let custom_fields = [
55 passport
56 .issuing_country
57 .map(|issuing_country| create_field(&issuing_country, Some("Issuing Country"))),
58 passport
59 .nationality
60 .map(|nationality| create_field(&nationality, Some("Nationality"))),
61 passport
62 .birth_date
63 .map(|birth_date| create_field(&birth_date, Some("Birth Date"))),
64 passport
65 .birth_place
66 .map(|birth_place| create_field(&birth_place, Some("Birth Place"))),
67 passport.sex.map(|sex| create_field(&sex, Some("Sex"))),
68 passport
69 .issue_date
70 .map(|issue_date| create_field(&issue_date, Some("Issue Date"))),
71 passport
72 .expiry_date
73 .map(|expiry_date| create_field(&expiry_date, Some("Expiry Date"))),
74 passport
75 .issuing_authority
76 .map(|issuing_authority| create_field(&issuing_authority, Some("Issuing Authority"))),
77 passport
78 .passport_type
79 .map(|passport_type| create_field(&passport_type, Some("Passport Type"))),
80 ]
81 .into_iter()
82 .flatten()
83 .collect();
84
85 (identity, custom_fields)
86}
87
88pub(super) fn person_name_to_identity(person_name: PersonNameCredential) -> (Identity, Vec<Field>) {
98 let last_name = [
100 person_name.surname_prefix.clone(),
101 person_name.surname.clone(),
102 person_name.surname2.clone(),
103 ]
104 .into_iter()
105 .flatten()
106 .map(String::from)
107 .reduce(|acc, part| format!("{acc} {part}"));
108
109 let identity = Identity {
110 title: person_name.title.map(Into::into),
111 first_name: person_name.given.map(Into::into),
112 middle_name: person_name.given2.map(Into::into),
113 last_name,
114 company: person_name.credentials.map(Into::into),
116 ..Default::default()
117 };
118
119 let custom_fields = [
121 person_name
122 .given_informal
123 .map(|given_informal| create_field(&given_informal, Some("Informal Given Name"))),
124 person_name
125 .generation
126 .map(|generation| create_field(&generation, Some("Generation"))),
127 ]
128 .into_iter()
129 .flatten()
130 .collect();
131
132 (identity, custom_fields)
133}
134
135pub(super) fn drivers_license_to_identity(
143 drivers_license: DriversLicenseCredential,
144) -> (Identity, Vec<Field>) {
145 let (first_name, last_name) = split_name(&drivers_license.full_name);
147
148 let identity = Identity {
149 first_name,
150 last_name,
151 state: drivers_license.territory.map(Into::into),
153 country: drivers_license.country.map(Into::into),
155 license_number: drivers_license.license_number.map(Into::into),
156 ..Default::default()
157 };
158
159 let custom_fields = [
161 drivers_license
162 .birth_date
163 .map(|birth_date| create_field(&birth_date, Some("Birth Date"))),
164 drivers_license
165 .issue_date
166 .map(|issue_date| create_field(&issue_date, Some("Issue Date"))),
167 drivers_license
168 .expiry_date
169 .map(|expiry_date| create_field(&expiry_date, Some("Expiry Date"))),
170 drivers_license
171 .issuing_authority
172 .map(|issuing_authority| create_field(&issuing_authority, Some("Issuing Authority"))),
173 drivers_license
174 .license_class
175 .map(|license_class| create_field(&license_class, Some("License Class"))),
176 ]
177 .into_iter()
178 .flatten()
179 .collect();
180
181 (identity, custom_fields)
182}
183
184pub(super) fn identity_document_to_identity(
193 identity_document: IdentityDocumentCredential,
194) -> (Identity, Vec<Field>) {
195 let (first_name, last_name) = split_name(&identity_document.full_name);
197
198 let identity = Identity {
199 first_name,
200 last_name,
201 ssn: identity_document.identification_number.map(Into::into),
203 passport_number: identity_document.document_number.map(Into::into),
205 ..Default::default()
206 };
207
208 let custom_fields = [
210 identity_document
211 .issuing_country
212 .map(|issuing_country| create_field(&issuing_country, Some("Issuing Country"))),
213 identity_document
214 .nationality
215 .map(|nationality| create_field(&nationality, Some("Nationality"))),
216 identity_document
217 .birth_date
218 .map(|birth_date| create_field(&birth_date, Some("Birth Date"))),
219 identity_document
220 .birth_place
221 .map(|birth_place| create_field(&birth_place, Some("Birth Place"))),
222 identity_document
223 .sex
224 .map(|sex| create_field(&sex, Some("Sex"))),
225 identity_document
226 .issue_date
227 .map(|issue_date| create_field(&issue_date, Some("Issue Date"))),
228 identity_document
229 .expiry_date
230 .map(|expiry_date| create_field(&expiry_date, Some("Expiry Date"))),
231 identity_document
232 .issuing_authority
233 .map(|issuing_authority| create_field(&issuing_authority, Some("Issuing Authority"))),
234 ]
235 .into_iter()
236 .flatten()
237 .collect();
238
239 (identity, custom_fields)
240}
241
242fn to_editable_field<T, U>(field: &Option<T>) -> Option<EditableField<U>>
243where
244 T: Clone + Into<EditableField<U>>,
245{
246 field.clone().map(|v| v.into())
247}
248
249fn split_name(
250 full_name: &Option<EditableField<EditableFieldString>>,
251) -> (Option<String>, Option<String>) {
252 full_name.clone().map_or((None, None), |name| {
253 let name = String::from(name);
254 let parts: Vec<&str> = name.split_whitespace().collect();
255 match parts.as_slice() {
256 [] => (None, None),
257 [first] => (Some(first.to_string()), None),
258 [first, rest @ ..] => (Some(first.to_string()), Some(rest.join(" "))),
259 }
260 })
261}
262
263impl From<&Identity> for PersonNameCredential {
264 fn from(identity: &Identity) -> Self {
265 PersonNameCredential {
266 title: to_editable_field(&identity.title),
267 given: to_editable_field(&identity.first_name),
268 given_informal: None,
269 given2: to_editable_field(&identity.middle_name),
270 surname_prefix: None,
271 surname: to_editable_field(&identity.last_name),
272 surname2: None,
273 credentials: to_editable_field(&identity.company),
274 generation: None,
275 }
277 }
278}
279
280impl From<&Identity> for AddressCredential {
281 fn from(identity: &Identity) -> Self {
282 let street_address = {
284 let address_lines: Vec<&str> =
285 [&identity.address1, &identity.address2, &identity.address3]
286 .into_iter()
287 .filter_map(|addr| addr.as_deref())
288 .collect();
289
290 if address_lines.is_empty() {
291 None
292 } else {
293 Some(address_lines.join("\n"))
294 }
295 };
296
297 AddressCredential {
298 street_address: street_address.map(|v| v.into()),
299 city: to_editable_field(&identity.city),
300 territory: to_editable_field(&identity.state),
301 country: to_editable_field(&identity.country),
302 tel: to_editable_field(&identity.phone),
303 postal_code: to_editable_field(&identity.postal_code),
304 }
305 }
306}
307
308impl From<&Identity> for PassportCredential {
309 fn from(identity: &Identity) -> Self {
310 let full_name = combine_name(
311 &identity.first_name,
312 &identity.middle_name,
313 &identity.last_name,
314 );
315
316 PassportCredential {
317 issuing_country: to_editable_field(&identity.country),
318 nationality: None,
319 full_name: full_name.map(|v| v.into()),
320 birth_date: None,
321 birth_place: None,
322 sex: None,
323 issue_date: None,
324 expiry_date: None,
325 issuing_authority: None,
326 passport_type: None,
327 passport_number: to_editable_field(&identity.passport_number),
328 national_identification_number: to_editable_field(&identity.ssn),
329 }
331 }
332}
333
334impl From<&Identity> for DriversLicenseCredential {
335 fn from(identity: &Identity) -> Self {
336 let full_name = combine_name(
337 &identity.first_name,
338 &identity.middle_name,
339 &identity.last_name,
340 );
341
342 DriversLicenseCredential {
343 full_name: full_name.map(|v| v.into()),
344 birth_date: None,
345 issue_date: None,
346 expiry_date: None,
347 issuing_authority: None,
348 territory: to_editable_field(&identity.state),
349 country: to_editable_field(&identity.country),
350 license_number: to_editable_field(&identity.license_number),
351 license_class: None,
352 }
354 }
355}
356
357impl From<&Identity> for IdentityDocumentCredential {
358 fn from(identity: &Identity) -> Self {
359 let full_name = combine_name(
360 &identity.first_name,
361 &identity.middle_name,
362 &identity.last_name,
363 );
364
365 IdentityDocumentCredential {
366 issuing_country: to_editable_field(&identity.country),
367 document_number: None,
368 identification_number: to_editable_field(&identity.ssn),
369 nationality: None,
370 full_name: full_name.map(|v| v.into()),
371 birth_date: None,
372 birth_place: None,
373 sex: None,
374 issue_date: None,
375 expiry_date: None,
376 issuing_authority: None,
377 }
379 }
380}
381
382impl From<Identity> for Vec<Credential> {
383 fn from(identity: Identity) -> Self {
384 let mut credentials = vec![];
385
386 let has_name_fields = identity.title.is_some()
388 || identity.first_name.is_some()
389 || identity.middle_name.is_some()
390 || identity.last_name.is_some()
391 || identity.company.is_some();
392
393 let has_address_fields = identity.address1.is_some()
395 || identity.city.is_some()
396 || identity.state.is_some()
397 || identity.country.is_some()
398 || identity.phone.is_some()
399 || identity.postal_code.is_some();
400
401 if has_name_fields {
403 credentials.push(Credential::PersonName(Box::new((&identity).into())));
404 }
405
406 if has_address_fields {
408 credentials.push(Credential::Address(Box::new((&identity).into())));
409 }
410
411 if identity.passport_number.is_some() {
413 credentials.push(Credential::Passport(Box::new((&identity).into())));
414 }
415
416 if identity.license_number.is_some() {
418 credentials.push(Credential::DriversLicense(Box::new((&identity).into())));
419 }
420
421 if identity.ssn.is_some() {
423 credentials.push(Credential::IdentityDocument(Box::new((&identity).into())));
424 }
425
426 let custom_fields: Vec<EditableFieldValue> = [
428 identity.email.as_ref().map(|email| {
429 EditableFieldValue::String(create_editable_field(
430 "Email".to_string(),
431 EditableFieldString(email.clone()),
432 ))
433 }),
434 identity.username.as_ref().map(|username| {
435 EditableFieldValue::String(create_editable_field(
436 "Username".to_string(),
437 EditableFieldString(username.clone()),
438 ))
439 }),
440 ]
441 .into_iter()
442 .flatten()
443 .collect();
444
445 if !custom_fields.is_empty() {
447 credentials.push(Credential::CustomFields(Box::new(CustomFieldsCredential {
448 id: None,
449 label: None,
450 fields: custom_fields,
451 extensions: vec![],
452 })));
453 }
454
455 credentials
456 }
457}
458
459pub(crate) fn combine_name(
460 first: &Option<String>,
461 middle: &Option<String>,
462 last: &Option<String>,
463) -> Option<String> {
464 let parts: Vec<&str> = [first.as_deref(), middle.as_deref(), last.as_deref()]
465 .into_iter()
466 .flatten()
467 .collect();
468
469 if parts.is_empty() {
470 None
471 } else {
472 Some(parts.join(" "))
473 }
474}
475
476#[cfg(test)]
477mod tests {
478 use credential_exchange_format::Credential;
479
480 use super::*;
481
482 #[test]
483 fn test_split_name_none() {
484 let full_name = None;
485 let (first, last) = split_name(&full_name);
486 assert_eq!(first, None);
487 assert_eq!(last, None);
488 }
489
490 #[test]
491 fn test_split_name_empty_string() {
492 let full_name = Some(EditableField {
493 value: EditableFieldString("".to_string()).into(),
494 label: None,
495 id: None,
496 extensions: None,
497 });
498 let (first, last) = split_name(&full_name);
499 assert_eq!(first, None);
500 assert_eq!(last, None);
501 }
502
503 #[test]
504 fn test_split_name_whitespace_only() {
505 let full_name = Some(EditableField {
506 value: EditableFieldString(" \t\n ".to_string()).into(),
507 label: None,
508 id: None,
509 extensions: None,
510 });
511 let (first, last) = split_name(&full_name);
512 assert_eq!(first, None);
513 assert_eq!(last, None);
514 }
515
516 #[test]
517 fn test_split_name_single_name() {
518 let full_name = Some(EditableField {
519 value: EditableFieldString("John".to_string()).into(),
520 label: None,
521 id: None,
522 extensions: None,
523 });
524 let (first, last) = split_name(&full_name);
525 assert_eq!(first, Some("John".to_string()));
526 assert_eq!(last, None);
527 }
528
529 #[test]
530 fn test_split_name_single_name_with_whitespace() {
531 let full_name = Some(EditableField {
532 value: EditableFieldString(" John ".to_string()).into(),
533 label: None,
534 id: None,
535 extensions: None,
536 });
537 let (first, last) = split_name(&full_name);
538 assert_eq!(first, Some("John".to_string()));
539 assert_eq!(last, None);
540 }
541
542 #[test]
543 fn test_split_name_first_last() {
544 let full_name = Some(EditableField {
545 value: EditableFieldString("John Doe".to_string()).into(),
546 label: None,
547 id: None,
548 extensions: None,
549 });
550 let (first, last) = split_name(&full_name);
551 assert_eq!(first, Some("John".to_string()));
552 assert_eq!(last, Some("Doe".to_string()));
553 }
554
555 #[test]
556 fn test_split_name_first_middle_last() {
557 let full_name = Some(EditableField {
558 value: EditableFieldString("John Michael Doe".to_string()).into(),
559 label: None,
560 id: None,
561 extensions: None,
562 });
563 let (first, last) = split_name(&full_name);
564 assert_eq!(first, Some("John".to_string()));
565 assert_eq!(last, Some("Michael Doe".to_string()));
566 }
567
568 #[test]
569 fn test_split_name_multiple_middle_names() {
570 let full_name = Some(EditableField {
571 value: EditableFieldString("John Michael Andrew Doe".to_string()).into(),
572 label: None,
573 id: None,
574 extensions: None,
575 });
576 let (first, last) = split_name(&full_name);
577 assert_eq!(first, Some("John".to_string()));
578 assert_eq!(last, Some("Michael Andrew Doe".to_string()));
579 }
580
581 #[test]
582 fn test_split_name_complex_surname() {
583 let full_name = Some(EditableField {
584 value: EditableFieldString("Jane van der Berg".to_string()).into(),
585 label: None,
586 id: None,
587 extensions: None,
588 });
589 let (first, last) = split_name(&full_name);
590 assert_eq!(first, Some("Jane".to_string()));
591 assert_eq!(last, Some("van der Berg".to_string()));
592 }
593
594 #[test]
595 fn test_split_name_hyphenated_surname() {
596 let full_name = Some(EditableField {
597 value: EditableFieldString("Mary Smith-Johnson".to_string()).into(),
598 label: None,
599 id: None,
600 extensions: None,
601 });
602 let (first, last) = split_name(&full_name);
603 assert_eq!(first, Some("Mary".to_string()));
604 assert_eq!(last, Some("Smith-Johnson".to_string()));
605 }
606
607 #[test]
608 fn test_split_name_extra_whitespace() {
609 let full_name = Some(EditableField {
610 value: EditableFieldString(" John Michael Doe ".to_string()).into(),
611 label: None,
612 id: None,
613 extensions: None,
614 });
615 let (first, last) = split_name(&full_name);
616 assert_eq!(first, Some("John".to_string()));
617 assert_eq!(last, Some("Michael Doe".to_string()));
618 }
619
620 #[test]
621 fn test_split_name_special_characters() {
622 let full_name = Some(EditableField {
623 value: EditableFieldString("José María González".to_string()).into(),
624 label: None,
625 id: None,
626 extensions: None,
627 });
628 let (first, last) = split_name(&full_name);
629 assert_eq!(first, Some("José".to_string()));
630 assert_eq!(last, Some("María González".to_string()));
631 }
632
633 #[test]
634 fn test_split_name_single_character_names() {
635 let full_name = Some(EditableField {
636 value: EditableFieldString("A B C".to_string()).into(),
637 label: None,
638 id: None,
639 extensions: None,
640 });
641 let (first, last) = split_name(&full_name);
642 assert_eq!(first, Some("A".to_string()));
643 assert_eq!(last, Some("B C".to_string()));
644 }
645
646 #[test]
647 fn test_identity_to_credentials() {
648 let identity = Identity {
649 title: Some("Dr.".to_string()),
650 first_name: Some("John".to_string()),
651 middle_name: Some("Michael".to_string()),
652 last_name: Some("Doe".to_string()),
653 address1: Some("123 Main St".to_string()),
654 address2: Some("Apt 456".to_string()),
655 address3: None,
656 city: Some("Anytown".to_string()),
657 state: Some("CA".to_string()),
658 postal_code: Some("12345".to_string()),
659 country: Some("US".to_string()),
660 company: Some("PhD".to_string()),
661 email: Some("[email protected]".to_string()),
662 phone: Some("+1234567890".to_string()),
663 ssn: Some("123-45-6789".to_string()),
664 username: Some("johndoe".to_string()),
665 passport_number: Some("P123456789".to_string()),
666 license_number: Some("DL123456".to_string()),
667 };
668
669 let credentials: Vec<Credential> = identity.into();
670
671 assert_eq!(credentials.len(), 6);
674
675 if let Credential::PersonName(person_name) = &credentials[0] {
677 assert_eq!(
678 person_name
679 .title
680 .as_ref()
681 .unwrap()
682 .value
683 .as_expected()
684 .unwrap()
685 .0,
686 "Dr."
687 );
688 assert_eq!(
689 person_name
690 .given
691 .as_ref()
692 .unwrap()
693 .value
694 .as_expected()
695 .unwrap()
696 .0,
697 "John"
698 );
699 assert_eq!(
700 person_name
701 .given2
702 .as_ref()
703 .unwrap()
704 .value
705 .as_expected()
706 .unwrap()
707 .0,
708 "Michael"
709 );
710 assert_eq!(
711 person_name
712 .surname
713 .as_ref()
714 .unwrap()
715 .value
716 .as_expected()
717 .unwrap()
718 .0,
719 "Doe"
720 );
721 assert_eq!(
722 person_name
723 .credentials
724 .as_ref()
725 .unwrap()
726 .value
727 .as_expected()
728 .unwrap()
729 .0,
730 "PhD"
731 );
732 } else {
733 panic!("Expected PersonName credential");
734 }
735
736 if let Credential::Address(address) = &credentials[1] {
738 assert_eq!(
739 address
740 .street_address
741 .as_ref()
742 .unwrap()
743 .value
744 .as_expected()
745 .unwrap()
746 .0,
747 "123 Main St\nApt 456"
748 );
749 assert_eq!(
750 address
751 .city
752 .as_ref()
753 .unwrap()
754 .value
755 .as_expected()
756 .unwrap()
757 .0,
758 "Anytown"
759 );
760 assert_eq!(
761 address
762 .territory
763 .as_ref()
764 .unwrap()
765 .value
766 .as_expected()
767 .unwrap()
768 .0,
769 "CA"
770 );
771 assert_eq!(
772 address
773 .country
774 .as_ref()
775 .unwrap()
776 .value
777 .as_expected()
778 .unwrap()
779 .0,
780 "US"
781 );
782 assert_eq!(
783 address.tel.as_ref().unwrap().value.as_expected().unwrap().0,
784 "+1234567890"
785 );
786 assert_eq!(
787 address
788 .postal_code
789 .as_ref()
790 .unwrap()
791 .value
792 .as_expected()
793 .unwrap()
794 .0,
795 "12345"
796 );
797 } else {
798 panic!("Expected Address credential");
799 }
800
801 if let Credential::Passport(passport) = &credentials[2] {
803 assert_eq!(
804 passport
805 .passport_number
806 .as_ref()
807 .unwrap()
808 .value
809 .as_expected()
810 .unwrap()
811 .0,
812 "P123456789"
813 );
814 assert_eq!(
815 passport
816 .full_name
817 .as_ref()
818 .unwrap()
819 .value
820 .as_expected()
821 .unwrap()
822 .0,
823 "John Michael Doe"
824 );
825 assert_eq!(
826 passport
827 .national_identification_number
828 .as_ref()
829 .unwrap()
830 .value
831 .as_expected()
832 .unwrap()
833 .0,
834 "123-45-6789"
835 );
836 assert_eq!(
837 passport
838 .issuing_country
839 .as_ref()
840 .unwrap()
841 .value
842 .as_expected()
843 .unwrap()
844 .0,
845 "US"
846 );
847 } else {
848 panic!("Expected Passport credential");
849 }
850
851 if let Credential::DriversLicense(license) = &credentials[3] {
853 assert_eq!(
854 license
855 .license_number
856 .as_ref()
857 .unwrap()
858 .value
859 .as_expected()
860 .unwrap()
861 .0,
862 "DL123456"
863 );
864 assert_eq!(
865 license
866 .full_name
867 .as_ref()
868 .unwrap()
869 .value
870 .as_expected()
871 .unwrap()
872 .0,
873 "John Michael Doe"
874 );
875 assert_eq!(
876 license
877 .territory
878 .as_ref()
879 .unwrap()
880 .value
881 .as_expected()
882 .unwrap()
883 .0,
884 "CA"
885 );
886 assert_eq!(
887 license
888 .country
889 .as_ref()
890 .unwrap()
891 .value
892 .as_expected()
893 .unwrap()
894 .0,
895 "US"
896 );
897 } else {
898 panic!("Expected DriversLicense credential");
899 }
900
901 if let Credential::IdentityDocument(identity_doc) = &credentials[4] {
903 assert_eq!(
904 identity_doc
905 .identification_number
906 .as_ref()
907 .unwrap()
908 .value
909 .as_expected()
910 .unwrap()
911 .0,
912 "123-45-6789"
913 );
914 assert_eq!(
915 identity_doc
916 .full_name
917 .as_ref()
918 .unwrap()
919 .value
920 .as_expected()
921 .unwrap()
922 .0,
923 "John Michael Doe"
924 );
925 } else {
926 panic!("Expected IdentityDocument credential");
927 }
928
929 if let Credential::CustomFields(custom_fields) = &credentials[5] {
931 assert_eq!(custom_fields.fields.len(), 2); let email_field = &custom_fields.fields[0];
935 if let EditableFieldValue::String(email_field) = email_field {
936 assert_eq!(email_field.label.as_ref().unwrap(), "Email");
937 assert_eq!(
938 email_field.value.as_expected().unwrap().0,
939 "[email protected]"
940 );
941 } else {
942 panic!("Expected email field to be of type String");
943 }
944
945 let username_field = &custom_fields.fields[1];
947 if let EditableFieldValue::String(username_field) = username_field {
948 assert_eq!(username_field.label.as_ref().unwrap(), "Username");
949 assert_eq!(username_field.value.as_expected().unwrap().0, "johndoe");
950 } else {
951 panic!("Expected username field to be of type String");
952 }
953 } else {
954 panic!("Expected CustomFields credential");
955 }
956 }
957
958 #[test]
959 fn test_identity_minimal_fields() {
960 let identity = Identity {
961 first_name: Some("Jane".to_string()),
962 last_name: Some("Smith".to_string()),
963 ..Default::default()
964 };
965
966 let credentials: Vec<Credential> = identity.into();
967
968 assert_eq!(credentials.len(), 1);
970
971 if let Credential::PersonName(person_name) = &credentials[0] {
972 assert_eq!(
973 person_name
974 .given
975 .as_ref()
976 .unwrap()
977 .value
978 .as_expected()
979 .unwrap()
980 .0,
981 "Jane"
982 );
983 assert_eq!(
984 person_name
985 .surname
986 .as_ref()
987 .unwrap()
988 .value
989 .as_expected()
990 .unwrap()
991 .0,
992 "Smith"
993 );
994 assert!(person_name.title.is_none());
995 assert!(person_name.given2.is_none());
996 } else {
997 panic!("Expected PersonName credential");
998 }
999 }
1000
1001 #[test]
1002 fn test_identity_license_only() {
1003 let identity = Identity {
1004 first_name: Some("Alice".to_string()),
1005 license_number: Some("LIC123456".to_string()),
1006 state: Some("NY".to_string()),
1007 ..Default::default()
1008 };
1009
1010 let credentials: Vec<Credential> = identity.into();
1011
1012 assert_eq!(credentials.len(), 3);
1014
1015 if let Credential::PersonName(person_name) = &credentials[0] {
1017 assert_eq!(
1018 person_name
1019 .given
1020 .as_ref()
1021 .unwrap()
1022 .value
1023 .as_expected()
1024 .unwrap()
1025 .0,
1026 "Alice"
1027 );
1028 } else {
1029 panic!("Expected PersonName credential");
1030 }
1031
1032 if let Credential::Address(address) = &credentials[1] {
1034 assert_eq!(
1035 address
1036 .territory
1037 .as_ref()
1038 .unwrap()
1039 .value
1040 .as_expected()
1041 .unwrap()
1042 .0,
1043 "NY"
1044 );
1045 } else {
1046 panic!("Expected Address credential");
1047 }
1048
1049 if let Credential::DriversLicense(license) = &credentials[2] {
1051 assert_eq!(
1052 license
1053 .license_number
1054 .as_ref()
1055 .unwrap()
1056 .value
1057 .as_expected()
1058 .unwrap()
1059 .0,
1060 "LIC123456"
1061 );
1062 assert_eq!(
1063 license
1064 .full_name
1065 .as_ref()
1066 .unwrap()
1067 .value
1068 .as_expected()
1069 .unwrap()
1070 .0,
1071 "Alice"
1072 );
1073 assert_eq!(
1074 license
1075 .territory
1076 .as_ref()
1077 .unwrap()
1078 .value
1079 .as_expected()
1080 .unwrap()
1081 .0,
1082 "NY"
1083 );
1084 } else {
1085 panic!("Expected DriversLicense credential");
1086 }
1087 }
1088
1089 #[test]
1090 fn test_identity_ssn_only() {
1091 let identity = Identity {
1092 first_name: Some("Bob".to_string()),
1093 ssn: Some("987-65-4321".to_string()),
1094 ..Default::default()
1095 };
1096
1097 let credentials: Vec<Credential> = identity.into();
1098
1099 assert_eq!(credentials.len(), 2);
1101
1102 if let Credential::IdentityDocument(identity_doc) = &credentials[1] {
1103 assert_eq!(
1104 identity_doc
1105 .identification_number
1106 .as_ref()
1107 .unwrap()
1108 .value
1109 .as_expected()
1110 .unwrap()
1111 .0,
1112 "987-65-4321"
1113 );
1114 assert_eq!(
1115 identity_doc
1116 .full_name
1117 .as_ref()
1118 .unwrap()
1119 .value
1120 .as_expected()
1121 .unwrap()
1122 .0,
1123 "Bob"
1124 );
1125 } else {
1126 panic!("Expected IdentityDocument credential");
1127 }
1128 }
1129
1130 #[test]
1131 fn test_identity_empty() {
1132 let identity = Identity::default();
1133
1134 let credentials: Vec<Credential> = identity.into();
1135
1136 assert_eq!(credentials.len(), 0);
1138 }
1139
1140 #[test]
1141 fn test_combine_name_helper() {
1142 assert_eq!(
1143 combine_name(
1144 &Some("John".to_string()),
1145 &Some("Michael".to_string()),
1146 &Some("Doe".to_string())
1147 ),
1148 Some("John Michael Doe".to_string())
1149 );
1150
1151 assert_eq!(
1152 combine_name(&Some("Jane".to_string()), &None, &Some("Smith".to_string())),
1153 Some("Jane Smith".to_string())
1154 );
1155
1156 assert_eq!(
1157 combine_name(&Some("Bob".to_string()), &None, &None),
1158 Some("Bob".to_string())
1159 );
1160
1161 assert_eq!(combine_name(&None, &None, &None), None);
1162 }
1163}