1use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
4use serde_yaml::{Mapping, Value};
5use url::Url;
6
7use crate::Date;
8
9#[derive(Debug, Clone, Eq, PartialEq)]
11pub enum Name {
12 Person(PersonName),
14
15 Entity(EntityName),
17
18 Anonymous,
22}
23
24impl Name {
25 pub fn is_person(&self) -> bool {
27 matches!(self, Self::Person(_))
28 }
29
30 pub fn is_entity(&self) -> bool {
32 matches!(self, Self::Entity(_))
33 }
34
35 pub fn is_anonymous(&self) -> bool {
37 matches!(self, Self::Anonymous)
38 }
39
40 pub fn as_person(&self) -> Option<&PersonName> {
42 if let Self::Person(p) = self {
43 Some(p)
44 } else {
45 None
46 }
47 }
48
49 pub fn as_entity(&self) -> Option<&EntityName> {
51 if let Self::Entity(e) = self {
52 Some(e)
53 } else {
54 None
55 }
56 }
57}
58
59impl Serialize for Name {
60 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
61 where
62 S: Serializer,
63 {
64 match self {
65 Self::Person(p) => p.serialize(serializer),
66 Self::Entity(e) => e.serialize(serializer),
67 Self::Anonymous => Mapping::from_iter([(
68 Value::String("name".into()),
69 Value::String("anonymous".into()),
70 )])
71 .serialize(serializer),
72 }
73 }
74}
75
76impl<'de> Deserialize<'de> for Name {
77 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
78 where
79 D: Deserializer<'de>,
80 {
81 let yaml = Mapping::deserialize(deserializer)?;
82 if let Some(name) = yaml.get("name") {
83 if let Value::String(name) = name {
84 if name == "anonymous" {
85 Ok(Name::Anonymous)
86 } else {
87 let entity: EntityName = serde_yaml::from_value(Value::Mapping(yaml))
88 .map_err(|e| D::Error::custom(e.to_string()))?;
89 Ok(Name::Entity(entity))
90 }
91 } else {
92 Err(D::Error::custom(
93 "'name' value must be a string".to_string(),
94 ))
95 }
96 } else {
97 let person: PersonName = serde_yaml::from_value(Value::Mapping(yaml))
98 .map_err(|e| D::Error::custom(e.to_string()))?;
99 Ok(Name::Person(person))
100 }
101 }
102}
103
104#[derive(Debug, Default, Clone, Eq, PartialEq, Serialize, Deserialize)]
108#[serde(rename_all = "kebab-case")]
109pub struct PersonName {
110 #[serde(default, skip_serializing_if = "Option::is_none")]
119 pub family_names: Option<String>,
120
121 #[serde(default, skip_serializing_if = "Option::is_none")]
123 pub given_names: Option<String>,
124
125 #[serde(default, skip_serializing_if = "Option::is_none")]
134 pub name_particle: Option<String>,
135
136 #[serde(default, skip_serializing_if = "Option::is_none")]
141 pub name_suffix: Option<String>,
142
143 #[serde(default, skip_serializing_if = "Option::is_none")]
145 pub affiliation: Option<String>,
146
147 #[serde(flatten)]
149 pub meta: NameMeta,
150}
151
152#[derive(Debug, Default, Clone, Eq, PartialEq, Serialize, Deserialize)]
156#[serde(rename_all = "kebab-case")]
157pub struct EntityName {
158 #[serde(default, skip_serializing_if = "Option::is_none")]
160 pub name: Option<String>,
161
162 #[serde(default, skip_serializing_if = "Option::is_none")]
166 pub date_start: Option<Date>,
167
168 #[serde(default, skip_serializing_if = "Option::is_none")]
172 pub date_end: Option<Date>,
173
174 #[serde(flatten)]
176 pub meta: NameMeta,
177}
178
179#[derive(Debug, Default, Clone, Eq, PartialEq, Serialize, Deserialize)]
181#[serde(rename_all = "kebab-case")]
182pub struct NameMeta {
183 #[serde(default, skip_serializing_if = "Option::is_none")]
187 pub orcid: Option<Url>,
188
189 #[serde(default, skip_serializing_if = "Option::is_none")]
191 pub address: Option<String>,
192
193 #[serde(default, skip_serializing_if = "Option::is_none")]
195 pub alias: Option<String>,
196
197 #[serde(default, skip_serializing_if = "Option::is_none")]
199 pub city: Option<String>,
200
201 #[serde(default, skip_serializing_if = "Option::is_none")]
203 pub country: Option<String>,
204
205 #[serde(default, skip_serializing_if = "Option::is_none")]
207 pub email: Option<String>,
208
209 #[serde(default, skip_serializing_if = "Option::is_none")]
211 pub post_code: Option<String>,
212
213 #[serde(default, skip_serializing_if = "Option::is_none")]
215 pub region: Option<String>,
216
217 #[serde(default, skip_serializing_if = "Option::is_none")]
219 pub location: Option<String>,
220
221 #[serde(default, skip_serializing_if = "Option::is_none")]
223 pub tel: Option<String>,
224
225 #[serde(default, skip_serializing_if = "Option::is_none")]
227 pub fax: Option<String>,
228
229 #[serde(default, skip_serializing_if = "Option::is_none")]
231 pub website: Option<Url>,
232}