1use std::fmt::{Display, Formatter};
4
5#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
26pub struct PersonName<'a> {
27 prefix: Option<&'a str>,
28 family: Option<&'a str>,
29 middle: Option<&'a str>,
30 given: Option<&'a str>,
31 suffix: Option<&'a str>,
32}
33
34#[derive(Debug, Copy, Clone)]
47pub struct PersonNameBuilder<'a> {
48 person_name: PersonName<'a>,
49}
50
51impl Display for PersonName<'_> {
52 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
53 let components: &[Option<&str>] = &[
54 self.prefix,
55 self.given,
56 self.middle,
57 self.family,
58 self.suffix,
59 ];
60
61 let mut c_iter = components.iter().flatten().peekable();
62
63 while let Some(component) = c_iter.next() {
64 if c_iter.peek().is_some() {
65 write!(f, "{} ", component)?
66 } else {
67 write!(f, "{}", component)?
68 }
69 }
70 Ok(())
71 }
72}
73
74impl<'a> PersonName<'a> {
75 pub fn prefix(&self) -> Option<&str> {
77 self.prefix
78 }
79 pub fn suffix(&self) -> Option<&str> {
81 self.suffix
82 }
83 pub fn family(&self) -> Option<&str> {
85 self.family
86 }
87 pub fn given(&self) -> Option<&str> {
89 self.given
90 }
91 pub fn middle(&self) -> Option<&str> {
93 self.middle
94 }
95 pub fn to_dicom_string(&self) -> String {
101 let mut name = String::new();
102
103 let components: &[Option<&str>] = &[
104 self.family,
105 self.given,
106 self.middle,
107 self.prefix,
108 self.suffix,
109 ];
110
111 let mut it = components.iter().rev().peekable();
112 while it.next_if(|component| component.is_none()).is_some() {}
114
115 let mut it = it.rev().peekable();
116 while let Some(option) = it.next() {
117 if let Some(component) = option {
118 name.push_str(component);
119 }
120 if it.peek().is_some() {
121 name.push('^');
122 }
123 }
124
125 name
126 }
127
128 pub fn from_text(slice: &'a str) -> PersonName<'a> {
135 let mut parts = slice.trim().split('^');
136
137 macro_rules! get_component {
138 () => {
139 parts
140 .next()
141 .and_then(|s| if s.is_empty() { None } else { Some(s) })
142 };
143 }
144
145 let family = get_component!();
146 let given = get_component!();
147 let middle = get_component!();
148 let prefix = get_component!();
149 let suffix = get_component!();
150
151 PersonName {
152 prefix,
153 given,
154 family,
155 middle,
156 suffix,
157 }
158 }
159
160 pub fn builder() -> PersonNameBuilder<'a> {
164 PersonNameBuilder::new()
165 }
166}
167
168impl<'a> PersonNameBuilder<'a> {
169 pub fn new() -> PersonNameBuilder<'a> {
170 PersonNameBuilder {
171 person_name: PersonName {
172 prefix: None,
173 family: None,
174 middle: None,
175 given: None,
176 suffix: None,
177 },
178 }
179 }
180
181 pub fn with_family(&mut self, family_name: &'a str) -> &mut Self {
183 self.person_name.family = Some(family_name);
184 self
185 }
186
187 pub fn with_middle(&mut self, middle_name: &'a str) -> &mut Self {
189 self.person_name.middle = Some(middle_name);
190 self
191 }
192
193 pub fn with_given(&mut self, given_name: &'a str) -> &mut Self {
195 self.person_name.given = Some(given_name);
196 self
197 }
198
199 pub fn with_prefix(&mut self, name_prefix: &'a str) -> &mut Self {
201 self.person_name.prefix = Some(name_prefix);
202 self
203 }
204
205 pub fn with_suffix(&mut self, name_suffix: &'a str) -> &mut Self {
207 self.person_name.suffix = Some(name_suffix);
208 self
209 }
210
211 pub fn build(&self) -> PersonName<'a> {
213 self.person_name
214 }
215}
216
217impl<'a> Default for PersonNameBuilder<'a> {
218 fn default() -> Self {
219 Self::new()
220 }
221}
222
223impl<'a> From<PersonNameBuilder<'a>> for PersonName<'a> {
224 fn from(builder: PersonNameBuilder<'a>) -> Self {
225 builder.build()
226 }
227}
228
229impl<'a> From<&mut PersonNameBuilder<'a>> for PersonName<'a> {
230 fn from(builder: &mut PersonNameBuilder<'a>) -> Self {
231 builder.build()
232 }
233}
234
235#[cfg(test)]
236mod tests {
237 use super::*;
238 #[test]
239 fn test_person_name_to_dicom_string() {
240 let p = PersonNameBuilder::new()
241 .with_given("John")
242 .with_family("Adams")
243 .build();
244 assert_eq!(p.to_dicom_string(), "Adams^John".to_string());
245
246 let p: PersonName = PersonNameBuilder::new().with_prefix("Rev.").into();
247 assert_eq!(p.to_dicom_string(), "^^^Rev.".to_string());
248
249 let p = PersonNameBuilder::new().with_suffix("B.A. M.Div.").build();
250 assert_eq!(p.to_dicom_string(), "^^^^B.A. M.Div.".to_string());
251 let p = PersonName {
252 prefix: Some("Rev."),
253 given: Some("John"),
254 middle: Some("Robert"),
255 family: Some("Adams"),
256 suffix: Some("B.A. M.Div."),
257 };
258 assert_eq!(
259 p.to_dicom_string(),
260 "Adams^John^Robert^Rev.^B.A. M.Div.".to_string()
261 );
262 let p = PersonName {
263 prefix: None,
264 given: Some("John"),
265 middle: Some("Robert"),
266 family: Some("Adams"),
267 suffix: Some("B.A. M.Div."),
268 };
269 assert_eq!(
270 p.to_dicom_string(),
271 "Adams^John^Robert^^B.A. M.Div.".to_string()
272 );
273 let p = PersonName {
274 prefix: Some("Rev."),
275 given: Some("John"),
276 middle: Some("Robert"),
277 family: Some("Adams"),
278 suffix: None,
279 };
280 assert_eq!(p.to_dicom_string(), "Adams^John^Robert^Rev.".to_string());
281 let p = PersonName {
282 prefix: None,
283 given: Some("John"),
284 middle: Some("Robert"),
285 family: Some("Adams"),
286 suffix: None,
287 };
288 assert_eq!(p.to_dicom_string(), "Adams^John^Robert".to_string());
289 let p = PersonName::builder().with_middle("Robert").build();
290 assert_eq!(p.to_dicom_string(), "^^Robert".to_string());
291 }
292 #[test]
293 fn test_person_name_to_string() {
294 let p = PersonName::builder()
295 .with_given("John")
296 .with_family("Adams")
297 .build();
298 assert_eq!(p.to_string(), "John Adams".to_string());
299
300 let p = PersonName::builder().with_prefix("Rev.").build();
301 assert_eq!(p.to_string(), "Rev.".to_string());
302
303 let p = PersonName::builder().with_suffix("B.A. M.Div.").build();
304 assert_eq!(p.to_string(), "B.A. M.Div.".to_string());
305 let p = PersonName {
306 prefix: Some("Rev."),
307 given: Some("John"),
308 middle: Some("Robert"),
309 family: Some("Adams"),
310 suffix: Some("B.A. M.Div."),
311 };
312 assert_eq!(
313 p.to_string(),
314 "Rev. John Robert Adams B.A. M.Div.".to_string()
315 );
316 let p = PersonName {
317 prefix: None,
318 given: Some("John"),
319 middle: Some("Robert"),
320 family: Some("Adams"),
321 suffix: Some("B.A. M.Div."),
322 };
323 assert_eq!(p.to_string(), "John Robert Adams B.A. M.Div.".to_string());
324 let p = PersonName {
325 prefix: Some("Rev."),
326 given: Some("John"),
327 middle: Some("Robert"),
328 family: Some("Adams"),
329 suffix: None,
330 };
331 assert_eq!(p.to_string(), "Rev. John Robert Adams".to_string());
332 let p = PersonName {
333 prefix: None,
334 given: Some("John"),
335 middle: Some("Robert"),
336 family: Some("Adams"),
337 suffix: None,
338 };
339 assert_eq!(p.to_string(), "John Robert Adams".to_string());
340 let p = PersonName::builder().with_middle("Robert").build();
341 assert_eq!(p.to_string(), "Robert".to_string());
342 }
343 #[test]
344 fn person_name_from_slice() {
345 assert_eq!(
346 PersonName::from_text("^^Robert"),
347 PersonName::builder().with_middle("Robert").build()
348 );
349 assert_eq!(
350 PersonName::from_text("^^^Rev."),
351 PersonName::builder().with_prefix("Rev.").build()
352 );
353 assert_eq!(
354 PersonName::from_text("^^^^B.A. M.Div."),
355 PersonName::builder().with_suffix("B.A. M.Div.").build()
356 );
357 assert_eq!(
358 PersonName::from_text("^^Robert"),
359 PersonName::builder().with_middle("Robert").build()
360 );
361 assert_eq!(
362 PersonName::from_text("^John"),
363 PersonName::builder().with_given("John").build()
364 );
365 assert_eq!(
366 PersonName::from_text("Adams"),
367 PersonName::builder().with_family("Adams").build()
368 );
369 assert_eq!(
370 PersonName::from_text("Adams^^^^B.A. M.Div."),
371 PersonName::builder()
372 .with_family("Adams")
373 .with_suffix("B.A. M.Div.")
374 .build()
375 );
376 assert_eq!(
377 PersonName::from_text("Adams^^Robert^^B.A. M.Div."),
378 PersonName {
379 prefix: None,
380 given: None,
381 middle: Some("Robert"),
382 family: Some("Adams"),
383 suffix: Some("B.A. M.Div."),
384 }
385 );
386 assert_eq!(
387 PersonName::from_text("Adams^John^Robert^Rev.^B.A. M.Div."),
388 PersonName {
389 prefix: Some("Rev."),
390 given: Some("John"),
391 middle: Some("Robert"),
392 family: Some("Adams"),
393 suffix: Some("B.A. M.Div."),
394 }
395 );
396 assert_eq!(
397 PersonName::from_text("Adams^ "),
398 PersonName {
399 prefix: None,
400 given: None,
401 middle: None,
402 family: Some("Adams"),
403 suffix: None,
404 }
405 );
406 }
407}