1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5#[serde(into = "i64", try_from = "i64")]
6pub enum Gender {
7 Male = 1,
8 Female = 2,
9 Other = 3,
10}
11
12impl From<Gender> for i64 {
13 fn from(g: Gender) -> i64 {
14 g as i64
15 }
16}
17
18impl TryFrom<i64> for Gender {
19 type Error = &'static str;
20
21 fn try_from(value: i64) -> Result<Self, Self::Error> {
22 match value {
23 1 => Ok(Gender::Male),
24 2 => Ok(Gender::Female),
25 3 => Ok(Gender::Other),
26 _ => Err("invalid gender value"),
27 }
28 }
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
33#[serde(into = "i64", try_from = "i64")]
34pub enum MaritalStatus {
35 Unmarried = 1,
36 Married = 2,
37 Divorced = 3,
38}
39
40impl From<MaritalStatus> for i64 {
41 fn from(m: MaritalStatus) -> i64 {
42 m as i64
43 }
44}
45
46impl TryFrom<i64> for MaritalStatus {
47 type Error = &'static str;
48
49 fn try_from(value: i64) -> Result<Self, Self::Error> {
50 match value {
51 1 => Ok(MaritalStatus::Unmarried),
52 2 => Ok(MaritalStatus::Married),
53 3 => Ok(MaritalStatus::Divorced),
54 _ => Err("invalid marital status value"),
55 }
56 }
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
61#[serde(into = "i64", try_from = "i64")]
62pub enum PhotoFormat {
63 Jpeg = 1,
64 Jpeg2000 = 2,
65 Avif = 3,
66 Webp = 4,
67}
68
69impl From<PhotoFormat> for i64 {
70 fn from(f: PhotoFormat) -> i64 {
71 f as i64
72 }
73}
74
75impl TryFrom<i64> for PhotoFormat {
76 type Error = &'static str;
77
78 fn try_from(value: i64) -> Result<Self, Self::Error> {
79 match value {
80 1 => Ok(PhotoFormat::Jpeg),
81 2 => Ok(PhotoFormat::Jpeg2000),
82 3 => Ok(PhotoFormat::Avif),
83 4 => Ok(PhotoFormat::Webp),
84 _ => Err("invalid photo format value"),
85 }
86 }
87}
88
89#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
91#[serde(into = "i64", try_from = "i64")]
92pub enum BiometricFormat {
93 Image = 0,
94 Template = 1,
95 Sound = 2,
96 BioHash = 3,
97}
98
99impl From<BiometricFormat> for i64 {
100 fn from(f: BiometricFormat) -> i64 {
101 f as i64
102 }
103}
104
105impl TryFrom<i64> for BiometricFormat {
106 type Error = &'static str;
107
108 fn try_from(value: i64) -> Result<Self, Self::Error> {
109 match value {
110 0 => Ok(BiometricFormat::Image),
111 1 => Ok(BiometricFormat::Template),
112 2 => Ok(BiometricFormat::Sound),
113 3 => Ok(BiometricFormat::BioHash),
114 _ => Err("invalid biometric format value"),
115 }
116 }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
121#[serde(into = "i64", try_from = "i64")]
122pub enum ImageSubFormat {
123 Png,
124 Jpeg,
125 Jpeg2000,
126 Avif,
127 Webp,
128 Tiff,
129 Wsq,
130 VendorSpecific(i64),
131}
132
133impl From<ImageSubFormat> for i64 {
134 fn from(f: ImageSubFormat) -> i64 {
135 match f {
136 ImageSubFormat::Png => 0,
137 ImageSubFormat::Jpeg => 1,
138 ImageSubFormat::Jpeg2000 => 2,
139 ImageSubFormat::Avif => 3,
140 ImageSubFormat::Webp => 4,
141 ImageSubFormat::Tiff => 5,
142 ImageSubFormat::Wsq => 6,
143 ImageSubFormat::VendorSpecific(v) => v,
144 }
145 }
146}
147
148impl TryFrom<i64> for ImageSubFormat {
149 type Error = &'static str;
150
151 fn try_from(value: i64) -> Result<Self, Self::Error> {
152 match value {
153 0 => Ok(ImageSubFormat::Png),
154 1 => Ok(ImageSubFormat::Jpeg),
155 2 => Ok(ImageSubFormat::Jpeg2000),
156 3 => Ok(ImageSubFormat::Avif),
157 4 => Ok(ImageSubFormat::Webp),
158 5 => Ok(ImageSubFormat::Tiff),
159 6 => Ok(ImageSubFormat::Wsq),
160 100..=200 => Ok(ImageSubFormat::VendorSpecific(value)),
161 _ => Err("invalid image sub-format value"),
162 }
163 }
164}
165
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
168#[serde(into = "i64", try_from = "i64")]
169pub enum TemplateSubFormat {
170 Ansi378,
171 Iso19794_2,
172 Nist,
173 VendorSpecific(i64),
174}
175
176impl From<TemplateSubFormat> for i64 {
177 fn from(f: TemplateSubFormat) -> i64 {
178 match f {
179 TemplateSubFormat::Ansi378 => 0,
180 TemplateSubFormat::Iso19794_2 => 1,
181 TemplateSubFormat::Nist => 2,
182 TemplateSubFormat::VendorSpecific(v) => v,
183 }
184 }
185}
186
187impl TryFrom<i64> for TemplateSubFormat {
188 type Error = &'static str;
189
190 fn try_from(value: i64) -> Result<Self, Self::Error> {
191 match value {
192 0 => Ok(TemplateSubFormat::Ansi378),
193 1 => Ok(TemplateSubFormat::Iso19794_2),
194 2 => Ok(TemplateSubFormat::Nist),
195 100..=200 => Ok(TemplateSubFormat::VendorSpecific(value)),
196 _ => Err("invalid template sub-format value"),
197 }
198 }
199}
200
201#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
203#[serde(into = "i64", try_from = "i64")]
204pub enum SoundSubFormat {
205 Wav = 0,
206 Mp3 = 1,
207}
208
209impl From<SoundSubFormat> for i64 {
210 fn from(f: SoundSubFormat) -> i64 {
211 f as i64
212 }
213}
214
215impl TryFrom<i64> for SoundSubFormat {
216 type Error = &'static str;
217
218 fn try_from(value: i64) -> Result<Self, Self::Error> {
219 match value {
220 0 => Ok(SoundSubFormat::Wav),
221 1 => Ok(SoundSubFormat::Mp3),
222 _ => Err("invalid sound sub-format value"),
223 }
224 }
225}
226
227#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
229#[serde(untagged)]
230pub enum BiometricSubFormat {
231 Image(ImageSubFormat),
232 Template(TemplateSubFormat),
233 Sound(SoundSubFormat),
234 Raw(i64),
235}
236
237impl BiometricSubFormat {
238 pub fn from_format_and_value(format: BiometricFormat, value: i64) -> Self {
239 match format {
240 BiometricFormat::Image => ImageSubFormat::try_from(value)
241 .map(BiometricSubFormat::Image)
242 .unwrap_or(BiometricSubFormat::Raw(value)),
243 BiometricFormat::Template => TemplateSubFormat::try_from(value)
244 .map(BiometricSubFormat::Template)
245 .unwrap_or(BiometricSubFormat::Raw(value)),
246 BiometricFormat::Sound => SoundSubFormat::try_from(value)
247 .map(BiometricSubFormat::Sound)
248 .unwrap_or(BiometricSubFormat::Raw(value)),
249 BiometricFormat::BioHash => BiometricSubFormat::Raw(value),
250 }
251 }
252
253 pub fn to_value(&self) -> i64 {
254 match self {
255 BiometricSubFormat::Image(f) => (*f).into(),
256 BiometricSubFormat::Template(f) => (*f).into(),
257 BiometricSubFormat::Sound(f) => (*f).into(),
258 BiometricSubFormat::Raw(v) => *v,
259 }
260 }
261}
262
263#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
265#[serde(rename_all = "lowercase")]
266pub enum VerificationStatus {
267 Verified,
268 Failed,
269 Skipped,
270}
271
272impl std::fmt::Display for VerificationStatus {
273 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
274 match self {
275 VerificationStatus::Verified => write!(f, "verified"),
276 VerificationStatus::Failed => write!(f, "failed"),
277 VerificationStatus::Skipped => write!(f, "skipped"),
278 }
279 }
280}
281
282#[cfg(test)]
283mod tests {
284 use super::*;
285
286 #[test]
288 fn test_gender_conversion() {
289 assert_eq!(i64::from(Gender::Male), 1);
290 assert_eq!(i64::from(Gender::Female), 2);
291 assert_eq!(i64::from(Gender::Other), 3);
292 assert_eq!(Gender::try_from(1).unwrap(), Gender::Male);
293 assert_eq!(Gender::try_from(2).unwrap(), Gender::Female);
294 assert_eq!(Gender::try_from(3).unwrap(), Gender::Other);
295 assert!(Gender::try_from(0).is_err());
296 assert!(Gender::try_from(4).is_err());
297 assert!(Gender::try_from(99).is_err());
298 }
299
300 #[test]
302 fn test_marital_status_conversion() {
303 assert_eq!(i64::from(MaritalStatus::Unmarried), 1);
304 assert_eq!(i64::from(MaritalStatus::Married), 2);
305 assert_eq!(i64::from(MaritalStatus::Divorced), 3);
306 assert_eq!(
307 MaritalStatus::try_from(1).unwrap(),
308 MaritalStatus::Unmarried
309 );
310 assert_eq!(MaritalStatus::try_from(2).unwrap(), MaritalStatus::Married);
311 assert_eq!(MaritalStatus::try_from(3).unwrap(), MaritalStatus::Divorced);
312 assert!(MaritalStatus::try_from(0).is_err());
313 assert!(MaritalStatus::try_from(4).is_err());
314 }
315
316 #[test]
318 fn test_photo_format_conversion() {
319 assert_eq!(i64::from(PhotoFormat::Jpeg), 1);
320 assert_eq!(i64::from(PhotoFormat::Jpeg2000), 2);
321 assert_eq!(i64::from(PhotoFormat::Avif), 3);
322 assert_eq!(i64::from(PhotoFormat::Webp), 4);
323 assert_eq!(PhotoFormat::try_from(1).unwrap(), PhotoFormat::Jpeg);
324 assert_eq!(PhotoFormat::try_from(2).unwrap(), PhotoFormat::Jpeg2000);
325 assert_eq!(PhotoFormat::try_from(3).unwrap(), PhotoFormat::Avif);
326 assert_eq!(PhotoFormat::try_from(4).unwrap(), PhotoFormat::Webp);
327 assert!(PhotoFormat::try_from(0).is_err());
328 assert!(PhotoFormat::try_from(5).is_err());
329 }
330
331 #[test]
333 fn test_biometric_format_conversion() {
334 assert_eq!(i64::from(BiometricFormat::Image), 0);
335 assert_eq!(i64::from(BiometricFormat::Template), 1);
336 assert_eq!(i64::from(BiometricFormat::Sound), 2);
337 assert_eq!(i64::from(BiometricFormat::BioHash), 3);
338 assert_eq!(
339 BiometricFormat::try_from(0).unwrap(),
340 BiometricFormat::Image
341 );
342 assert_eq!(
343 BiometricFormat::try_from(1).unwrap(),
344 BiometricFormat::Template
345 );
346 assert_eq!(
347 BiometricFormat::try_from(2).unwrap(),
348 BiometricFormat::Sound
349 );
350 assert_eq!(
351 BiometricFormat::try_from(3).unwrap(),
352 BiometricFormat::BioHash
353 );
354 assert!(BiometricFormat::try_from(-1).is_err());
355 assert!(BiometricFormat::try_from(4).is_err());
356 }
357
358 #[test]
360 fn test_image_subformat_all_variants() {
361 assert_eq!(i64::from(ImageSubFormat::Png), 0);
362 assert_eq!(i64::from(ImageSubFormat::Jpeg), 1);
363 assert_eq!(i64::from(ImageSubFormat::Jpeg2000), 2);
364 assert_eq!(i64::from(ImageSubFormat::Avif), 3);
365 assert_eq!(i64::from(ImageSubFormat::Webp), 4);
366 assert_eq!(i64::from(ImageSubFormat::Tiff), 5);
367 assert_eq!(i64::from(ImageSubFormat::Wsq), 6);
368 assert_eq!(i64::from(ImageSubFormat::VendorSpecific(150)), 150);
369
370 assert_eq!(ImageSubFormat::try_from(0).unwrap(), ImageSubFormat::Png);
371 assert_eq!(ImageSubFormat::try_from(1).unwrap(), ImageSubFormat::Jpeg);
372 assert_eq!(
373 ImageSubFormat::try_from(2).unwrap(),
374 ImageSubFormat::Jpeg2000
375 );
376 assert_eq!(ImageSubFormat::try_from(3).unwrap(), ImageSubFormat::Avif);
377 assert_eq!(ImageSubFormat::try_from(4).unwrap(), ImageSubFormat::Webp);
378 assert_eq!(ImageSubFormat::try_from(5).unwrap(), ImageSubFormat::Tiff);
379 assert_eq!(ImageSubFormat::try_from(6).unwrap(), ImageSubFormat::Wsq);
380 }
381
382 #[test]
383 fn test_image_subformat_vendor_specific() {
384 let vendor = ImageSubFormat::try_from(150).unwrap();
385 assert!(matches!(vendor, ImageSubFormat::VendorSpecific(150)));
386 assert_eq!(i64::from(vendor), 150);
387
388 let vendor_100 = ImageSubFormat::try_from(100).unwrap();
390 assert!(matches!(vendor_100, ImageSubFormat::VendorSpecific(100)));
391
392 let vendor_200 = ImageSubFormat::try_from(200).unwrap();
393 assert!(matches!(vendor_200, ImageSubFormat::VendorSpecific(200)));
394 }
395
396 #[test]
397 fn test_image_subformat_invalid_values() {
398 assert!(ImageSubFormat::try_from(7).is_err());
400 assert!(ImageSubFormat::try_from(50).is_err());
401 assert!(ImageSubFormat::try_from(99).is_err());
402 assert!(ImageSubFormat::try_from(201).is_err());
404 assert!(ImageSubFormat::try_from(-1).is_err());
405 }
406
407 #[test]
409 fn test_template_subformat_all_variants() {
410 assert_eq!(i64::from(TemplateSubFormat::Ansi378), 0);
411 assert_eq!(i64::from(TemplateSubFormat::Iso19794_2), 1);
412 assert_eq!(i64::from(TemplateSubFormat::Nist), 2);
413 assert_eq!(i64::from(TemplateSubFormat::VendorSpecific(175)), 175);
414
415 assert_eq!(
416 TemplateSubFormat::try_from(0).unwrap(),
417 TemplateSubFormat::Ansi378
418 );
419 assert_eq!(
420 TemplateSubFormat::try_from(1).unwrap(),
421 TemplateSubFormat::Iso19794_2
422 );
423 assert_eq!(
424 TemplateSubFormat::try_from(2).unwrap(),
425 TemplateSubFormat::Nist
426 );
427 }
428
429 #[test]
430 fn test_template_subformat_vendor_specific() {
431 let vendor = TemplateSubFormat::try_from(100).unwrap();
432 assert!(matches!(vendor, TemplateSubFormat::VendorSpecific(100)));
433
434 let vendor = TemplateSubFormat::try_from(200).unwrap();
435 assert!(matches!(vendor, TemplateSubFormat::VendorSpecific(200)));
436 }
437
438 #[test]
439 fn test_template_subformat_invalid_values() {
440 assert!(TemplateSubFormat::try_from(3).is_err());
441 assert!(TemplateSubFormat::try_from(50).is_err());
442 assert!(TemplateSubFormat::try_from(99).is_err());
443 assert!(TemplateSubFormat::try_from(201).is_err());
444 assert!(TemplateSubFormat::try_from(-1).is_err());
445 }
446
447 #[test]
449 fn test_sound_subformat_conversion() {
450 assert_eq!(i64::from(SoundSubFormat::Wav), 0);
451 assert_eq!(i64::from(SoundSubFormat::Mp3), 1);
452 assert_eq!(SoundSubFormat::try_from(0).unwrap(), SoundSubFormat::Wav);
453 assert_eq!(SoundSubFormat::try_from(1).unwrap(), SoundSubFormat::Mp3);
454 assert!(SoundSubFormat::try_from(2).is_err());
455 assert!(SoundSubFormat::try_from(-1).is_err());
456 }
457
458 #[test]
460 fn test_biometric_subformat_from_format() {
461 let sub = BiometricSubFormat::from_format_and_value(BiometricFormat::Image, 6);
463 assert!(matches!(
464 sub,
465 BiometricSubFormat::Image(ImageSubFormat::Wsq)
466 ));
467
468 let sub = BiometricSubFormat::from_format_and_value(BiometricFormat::Image, 0);
469 assert!(matches!(
470 sub,
471 BiometricSubFormat::Image(ImageSubFormat::Png)
472 ));
473
474 let sub = BiometricSubFormat::from_format_and_value(BiometricFormat::Template, 1);
476 assert!(matches!(
477 sub,
478 BiometricSubFormat::Template(TemplateSubFormat::Iso19794_2)
479 ));
480
481 let sub = BiometricSubFormat::from_format_and_value(BiometricFormat::Template, 0);
482 assert!(matches!(
483 sub,
484 BiometricSubFormat::Template(TemplateSubFormat::Ansi378)
485 ));
486
487 let sub = BiometricSubFormat::from_format_and_value(BiometricFormat::Sound, 0);
489 assert!(matches!(
490 sub,
491 BiometricSubFormat::Sound(SoundSubFormat::Wav)
492 ));
493
494 let sub = BiometricSubFormat::from_format_and_value(BiometricFormat::Sound, 1);
495 assert!(matches!(
496 sub,
497 BiometricSubFormat::Sound(SoundSubFormat::Mp3)
498 ));
499
500 let sub = BiometricSubFormat::from_format_and_value(BiometricFormat::BioHash, 0);
502 assert!(matches!(sub, BiometricSubFormat::Raw(0)));
503
504 let sub = BiometricSubFormat::from_format_and_value(BiometricFormat::BioHash, 42);
505 assert!(matches!(sub, BiometricSubFormat::Raw(42)));
506 }
507
508 #[test]
509 fn test_biometric_subformat_invalid_returns_raw() {
510 let sub = BiometricSubFormat::from_format_and_value(BiometricFormat::Image, 50);
512 assert!(matches!(sub, BiometricSubFormat::Raw(50)));
513
514 let sub = BiometricSubFormat::from_format_and_value(BiometricFormat::Template, 50);
516 assert!(matches!(sub, BiometricSubFormat::Raw(50)));
517
518 let sub = BiometricSubFormat::from_format_and_value(BiometricFormat::Sound, 99);
520 assert!(matches!(sub, BiometricSubFormat::Raw(99)));
521 }
522
523 #[test]
524 fn test_biometric_subformat_to_value() {
525 let sub = BiometricSubFormat::Image(ImageSubFormat::Jpeg);
527 assert_eq!(sub.to_value(), 1);
528
529 let sub = BiometricSubFormat::Image(ImageSubFormat::VendorSpecific(150));
530 assert_eq!(sub.to_value(), 150);
531
532 let sub = BiometricSubFormat::Template(TemplateSubFormat::Iso19794_2);
534 assert_eq!(sub.to_value(), 1);
535
536 let sub = BiometricSubFormat::Template(TemplateSubFormat::VendorSpecific(175));
537 assert_eq!(sub.to_value(), 175);
538
539 let sub = BiometricSubFormat::Sound(SoundSubFormat::Mp3);
541 assert_eq!(sub.to_value(), 1);
542
543 let sub = BiometricSubFormat::Raw(999);
545 assert_eq!(sub.to_value(), 999);
546 }
547
548 #[test]
550 fn test_verification_status_display() {
551 assert_eq!(format!("{}", VerificationStatus::Verified), "verified");
552 assert_eq!(format!("{}", VerificationStatus::Failed), "failed");
553 assert_eq!(format!("{}", VerificationStatus::Skipped), "skipped");
554 }
555
556 #[test]
557 fn test_verification_status_json_serialization() {
558 let verified = VerificationStatus::Verified;
559 let json = serde_json::to_string(&verified).unwrap();
560 assert_eq!(json, "\"verified\"");
561
562 let failed = VerificationStatus::Failed;
563 let json = serde_json::to_string(&failed).unwrap();
564 assert_eq!(json, "\"failed\"");
565
566 let skipped = VerificationStatus::Skipped;
567 let json = serde_json::to_string(&skipped).unwrap();
568 assert_eq!(json, "\"skipped\"");
569
570 let parsed: VerificationStatus = serde_json::from_str("\"verified\"").unwrap();
572 assert_eq!(parsed, VerificationStatus::Verified);
573 }
574
575 #[test]
577 fn test_gender_traits() {
578 let g1 = Gender::Male;
579 let g2 = g1; assert_eq!(g1, g2);
581 assert_ne!(g1, Gender::Female);
582 assert!(format!("{:?}", g1).contains("Male"));
584 }
585
586 #[test]
587 fn test_verification_status_traits() {
588 let v1 = VerificationStatus::Verified;
589 let v2 = v1; assert_eq!(v1, v2);
591 assert_ne!(v1, VerificationStatus::Failed);
592 assert!(format!("{:?}", v1).contains("Verified"));
594 }
595
596 #[test]
597 fn test_biometric_subformat_copy() {
598 let sub1 = BiometricSubFormat::Image(ImageSubFormat::Jpeg);
599 let sub2 = sub1; assert_eq!(sub1, sub2);
601 }
602}