1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
- //! Code for working with genders.
- use std::str::FromStr;
- use std::fmt;
- use thiserror::Error;
- #[derive(Error, Debug)]
- pub enum GenderError {
- #[error("could not parse gender from string")]
- #[allow(dead_code)]
- ParseError
- }
- /// A gender representation.
- #[derive(Debug, PartialEq, Eq, Hash, Clone)]
- pub enum Gender {
- Unknown,
- Ambiguous,
- Female,
- Male,
- Open(String)
- }
- impl FromStr for Gender {
- type Err = GenderError;
- fn from_str(s: &str) -> Result<Gender, GenderError> {
- Ok(s.into())
- }
- }
- impl From<&str> for Gender {
- fn from(s: &str) -> Gender {
- let sg = s.trim().to_lowercase();
- match sg.as_str() {
- "unknown" => Gender::Unknown,
- "ambiguous" => Gender::Ambiguous,
- "female" => Gender::Female,
- "male" => Gender::Male,
- _ => Gender::Open(sg)
- }
- }
- }
- impl From<String> for Gender {
- fn from(s: String) -> Gender {
- s.as_str().into()
- }
- }
- impl <T> From<&T> for Gender where T: Into<Gender> + Clone {
- fn from(obj: &T) -> Gender {
- obj.clone().into()
- }
- }
- impl fmt::Display for Gender {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Gender::Unknown => f.write_str("unknown"),
- Gender::Ambiguous => f.write_str("ambiguous"),
- Gender::Female => f.write_str("female"),
- Gender::Male => f.write_str("male"),
- Gender::Open(s) => f.write_str(s.as_str())
- }
- }
- }
- impl Gender {
- /// Merge a gender record with another. If the two records
- /// disagree, the result is [Gender::Ambiguous].
- pub fn merge(&self, other: &Gender) -> Gender {
- match (self, other) {
- (Gender::Unknown, g) => g.clone(),
- (g, Gender::Unknown) => g.clone(),
- (g1, g2) if g1 == g2 => g2.clone(),
- _ => Gender::Ambiguous
- }
- }
- }
- pub fn resolve_gender<I,G>(genders: I) -> Gender
- where I: IntoIterator<Item=G>,
- G: Into<Gender>
- {
- let mut gender = Gender::Unknown;
- for g in genders {
- let g: Gender = g.into();
- gender = gender.merge(&g);
- }
- gender.to_owned()
- }
- #[test]
- pub fn test_resolve_empty() {
- let g = resolve_gender(Vec::<String>::new());
- assert_eq!(g, Gender::Unknown);
- }
- #[test]
- pub fn test_resolve_female() {
- let g = resolve_gender(vec!["female"]);
- assert_eq!(g, Gender::Female);
- }
- #[test]
- pub fn test_resolve_male() {
- let g = resolve_gender(vec!["male"]);
- assert_eq!(g, Gender::Male);
- }
- #[test]
- pub fn test_resolve_mf() {
- let g = resolve_gender(vec!["male", "female"]);
- assert_eq!(g, Gender::Ambiguous);
- }
- #[test]
- pub fn test_resolve_f_unknown() {
- let g = resolve_gender(vec!["female", "unknown"]);
- assert_eq!(g, Gender::Female);
- }
- #[test]
- pub fn test_resolve_u_f() {
- let g = resolve_gender(vec!["unknown", "female"]);
- assert_eq!(g, Gender::Female);
- }
|