1use thiserror::Error;
2
3use crate::{EMLError, EMLValueResultExt as _, utils::StringValueData};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum Gender {
8 Male,
10 Female,
12 Unknown,
14}
15
16impl Gender {
17 pub fn new(s: impl AsRef<str>) -> Result<Self, EMLError> {
19 Self::from_eml_value(s).wrap_value_error()
20 }
21
22 pub fn from_eml_value(s: impl AsRef<str>) -> Result<Self, UnknownGenderError> {
24 let data = s.as_ref();
25 match data {
26 "male" => Ok(Gender::Male),
27 "female" => Ok(Gender::Female),
28 "unknown" => Ok(Gender::Unknown),
29 _ => Err(UnknownGenderError(data.to_string())),
30 }
31 }
32
33 pub fn to_eml_value(&self) -> &'static str {
35 match self {
36 Gender::Male => "male",
37 Gender::Female => "female",
38 Gender::Unknown => "unknown",
39 }
40 }
41}
42
43#[derive(Debug, Clone, Error, PartialEq, Eq)]
45#[error("Unknown gender: {0}")]
46pub struct UnknownGenderError(String);
47
48impl StringValueData for Gender {
49 type Error = UnknownGenderError;
50
51 fn parse_from_str(s: &str) -> Result<Self, Self::Error>
52 where
53 Self: Sized,
54 {
55 Self::from_eml_value(s)
56 }
57
58 fn to_raw_value(&self) -> String {
59 self.to_eml_value().to_string()
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn test_valid_gender_types() {
69 let valid_genders = ["male", "female", "unknown"];
70 for gender in valid_genders {
71 assert!(
72 Gender::from_eml_value(gender).is_ok(),
73 "Gender should accept valid gender: {}",
74 gender
75 );
76 }
77 }
78
79 #[test]
80 fn test_invalid_gender_types() {
81 let invalid_genders = ["", "test", "abc"];
82 for gender in invalid_genders {
83 assert!(
84 Gender::from_eml_value(gender).is_err(),
85 "Gender should reject invalid gender: {}",
86 gender
87 );
88 }
89 }
90}