1use std::error::Error;
5use std::fmt;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum MRZError {
10 InvalidMRZInput,
12
13 InvalidDocumentNumber,
15
16 InvalidBirthDate,
18
19 InvalidExpiryDate,
21
22 InvalidOptionalData,
24
25 InvalidMRZValue,
27
28 Custom(String),
30}
31
32impl MRZError {
33 pub fn invalid_mrz_input() -> Self {
35 MRZError::InvalidMRZInput
36 }
37
38 pub fn invalid_document_number() -> Self {
39 MRZError::InvalidDocumentNumber
40 }
41
42 pub fn invalid_birth_date() -> Self {
43 MRZError::InvalidBirthDate
44 }
45
46 pub fn invalid_expiry_date() -> Self {
47 MRZError::InvalidExpiryDate
48 }
49
50 pub fn invalid_optional_data() -> Self {
51 MRZError::InvalidOptionalData
52 }
53
54 pub fn invalid_mrz_value() -> Self {
55 MRZError::InvalidMRZValue
56 }
57
58 pub fn custom<M: Into<String>>(msg: M) -> Self {
60 MRZError::Custom(msg.into())
61 }
62
63 fn short_message(&self) -> &str {
65 match self {
66 MRZError::InvalidMRZInput => "Invalid MRZ parser input",
67 MRZError::InvalidDocumentNumber => "Document number hash mismatch",
68 MRZError::InvalidBirthDate => "Birth date hash mismatch",
69 MRZError::InvalidExpiryDate => "Expiry date hash mismatch",
70 MRZError::InvalidOptionalData => "Optional data hash mismatch",
71 MRZError::InvalidMRZValue => "Final hash mismatch",
72 MRZError::Custom(s) => s.as_str(),
73 }
74 }
75}
76
77impl fmt::Display for MRZError {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 write!(
80 f,
81 "{}. If you think this is a mistake, please file an issue at {}/issues",
82 self.short_message(),
83 env!("CARGO_PKG_REPOSITORY")
84 )
85 }
86}
87
88impl Error for MRZError {}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn display_contains_message_and_link() {
96 let e = MRZError::invalid_mrz_input();
97 let s = format!("{}", e);
98 assert!(s.contains("Invalid MRZ parser input"));
99 assert!(s.contains(concat!(env!("CARGO_PKG_REPOSITORY"), "/issues")));
100 }
101
102 #[test]
103 fn custom_error_message() {
104 let e = MRZError::custom("something went wrong");
105 let s = format!("{}", e);
106 assert!(s.contains("something went wrong"));
107 assert!(s.contains(concat!(env!("CARGO_PKG_REPOSITORY"), "/issues")));
108 }
109
110 #[test]
111 fn variants_have_expected_short_messages() {
112 assert_eq!(
113 MRZError::InvalidDocumentNumber.short_message(),
114 "Document number hash mismatch"
115 );
116 assert_eq!(
117 MRZError::InvalidBirthDate.short_message(),
118 "Birth date hash mismatch"
119 );
120 assert_eq!(
121 MRZError::InvalidExpiryDate.short_message(),
122 "Expiry date hash mismatch"
123 );
124 assert_eq!(
125 MRZError::InvalidOptionalData.short_message(),
126 "Optional data hash mismatch"
127 );
128 assert_eq!(
129 MRZError::InvalidMRZValue.short_message(),
130 "Final hash mismatch"
131 );
132 }
133}