use std::borrow::Cow;
use std::fmt::{Display, Formatter};
use std::mem;
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub struct PersonName<'a> {
prefix: Option<Cow<'a, str>>,
family: Option<Cow<'a, str>>,
middle: Option<Cow<'a, str>>,
given: Option<Cow<'a, str>>,
suffix: Option<Cow<'a, str>>,
}
#[derive(Debug, Clone)]
pub struct PersonNameBuilder<'a> {
person_name: PersonName<'a>,
}
impl Display for PersonName<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let components = &[
&self.prefix,
&self.given,
&self.middle,
&self.family,
&self.suffix,
];
let mut c_iter = components.iter().copied().flatten().peekable();
while let Some(component) = c_iter.next() {
if c_iter.peek().is_some() {
write!(f, "{component} ")?
} else {
write!(f, "{component}")?
}
}
Ok(())
}
}
impl<'a> PersonName<'a> {
pub fn prefix(&self) -> Option<&str> {
self.prefix.as_deref()
}
pub fn suffix(&self) -> Option<&str> {
self.suffix.as_deref()
}
pub fn family(&self) -> Option<&str> {
self.family.as_deref()
}
pub fn given(&self) -> Option<&str> {
self.given.as_deref()
}
pub fn middle(&self) -> Option<&str> {
self.middle.as_deref()
}
pub fn to_dicom_string(&self) -> String {
let mut name = String::new();
let components = &[
&self.family,
&self.given,
&self.middle,
&self.prefix,
&self.suffix,
];
let mut it = components.iter().rev().peekable();
while it.next_if(|component| component.is_none()).is_some() {}
let mut it = it.rev().peekable();
while let Some(option) = it.next() {
if let Some(component) = option {
name.push_str(component);
}
if it.peek().is_some() {
name.push('^');
}
}
name
}
pub fn from_text(slice: &'a str) -> PersonName<'a> {
let mut parts = slice.trim().split('^');
macro_rules! get_component {
() => {
parts
.next()
.and_then(|s| if s.is_empty() { None } else { Some(s.into()) })
};
}
let family = get_component!();
let given = get_component!();
let middle = get_component!();
let prefix = get_component!();
let suffix = get_component!();
PersonName {
prefix,
given,
family,
middle,
suffix,
}
}
pub fn builder() -> PersonNameBuilder<'a> {
PersonNameBuilder::new()
}
}
impl<'a> PersonNameBuilder<'a> {
pub fn new() -> PersonNameBuilder<'a> {
PersonNameBuilder {
person_name: PersonName {
prefix: None,
family: None,
middle: None,
given: None,
suffix: None,
},
}
}
pub fn with_family(&mut self, family_name: impl Into<Cow<'a, str>>) -> &mut Self {
self.person_name.family = Some(family_name.into());
self
}
pub fn with_middle(&mut self, middle_name: impl Into<Cow<'a, str>>) -> &mut Self {
self.person_name.middle = Some(middle_name.into());
self
}
pub fn with_given(&mut self, given_name: impl Into<Cow<'a, str>>) -> &mut Self {
self.person_name.given = Some(given_name.into());
self
}
pub fn with_prefix(&mut self, name_prefix: impl Into<Cow<'a, str>>) -> &mut Self {
self.person_name.prefix = Some(name_prefix.into());
self
}
pub fn with_suffix(&mut self, name_suffix: impl Into<Cow<'a, str>>) -> &mut Self {
self.person_name.suffix = Some(name_suffix.into());
self
}
pub fn build(&mut self) -> PersonName<'a> {
mem::take(self).person_name
}
}
impl Default for PersonNameBuilder<'_> {
fn default() -> Self {
Self::new()
}
}
impl<'a> From<PersonNameBuilder<'a>> for PersonName<'a> {
fn from(mut builder: PersonNameBuilder<'a>) -> Self {
builder.build()
}
}
impl<'a> From<&mut PersonNameBuilder<'a>> for PersonName<'a> {
fn from(builder: &mut PersonNameBuilder<'a>) -> Self {
builder.build()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_person_name_to_dicom_string() {
let p = PersonNameBuilder::new()
.with_given("John")
.with_family("Adams")
.build();
assert_eq!(p.to_dicom_string(), "Adams^John".to_string());
let p: PersonName = PersonNameBuilder::new().with_prefix("Rev.").into();
assert_eq!(p.to_dicom_string(), "^^^Rev.".to_string());
let p = PersonNameBuilder::new().with_suffix("B.A. M.Div.").build();
assert_eq!(p.to_dicom_string(), "^^^^B.A. M.Div.".to_string());
let p = PersonName {
prefix: Some("Rev.".into()),
given: Some("John".into()),
middle: Some("Robert".into()),
family: Some("Adams".into()),
suffix: Some("B.A. M.Div.".into()),
};
assert_eq!(
p.to_dicom_string(),
"Adams^John^Robert^Rev.^B.A. M.Div.".to_string()
);
let p = PersonName {
prefix: None,
given: Some("John".into()),
middle: Some("Robert".into()),
family: Some("Adams".into()),
suffix: Some("B.A. M.Div.".into()),
};
assert_eq!(
p.to_dicom_string(),
"Adams^John^Robert^^B.A. M.Div.".to_string()
);
let p = PersonName {
prefix: Some("Rev.".into()),
given: Some("John".into()),
middle: Some("Robert".into()),
family: Some("Adams".into()),
suffix: None,
};
assert_eq!(p.to_dicom_string(), "Adams^John^Robert^Rev.".to_string());
let p = PersonName {
prefix: None,
given: Some("John".into()),
middle: Some("Robert".into()),
family: Some("Adams".into()),
suffix: None,
};
assert_eq!(p.to_dicom_string(), "Adams^John^Robert".to_string());
let p = PersonName::builder().with_middle("Robert").build();
assert_eq!(p.to_dicom_string(), "^^Robert".to_string());
}
#[test]
fn test_person_name_to_string() {
let p = PersonName::builder()
.with_given("John")
.with_family("Adams")
.build();
assert_eq!(p.to_string(), "John Adams".to_string());
let p = PersonName::builder().with_prefix("Rev.").build();
assert_eq!(p.to_string(), "Rev.".to_string());
let p = PersonName::builder().with_suffix("B.A. M.Div.").build();
assert_eq!(p.to_string(), "B.A. M.Div.".to_string());
let p = PersonName {
prefix: Some("Rev.".into()),
given: Some("John".into()),
middle: Some("Robert".into()),
family: Some("Adams".into()),
suffix: Some("B.A. M.Div.".into()),
};
assert_eq!(
p.to_string(),
"Rev. John Robert Adams B.A. M.Div.".to_string()
);
let p = PersonName {
prefix: None,
given: Some("John".into()),
middle: Some("Robert".into()),
family: Some("Adams".into()),
suffix: Some("B.A. M.Div.".into()),
};
assert_eq!(p.to_string(), "John Robert Adams B.A. M.Div.".to_string());
let p = PersonName {
prefix: Some("Rev.".into()),
given: Some("John".into()),
middle: Some("Robert".into()),
family: Some("Adams".into()),
suffix: None,
};
assert_eq!(p.to_string(), "Rev. John Robert Adams".to_string());
let p = PersonName {
prefix: None,
given: Some("John".into()),
middle: Some("Robert".into()),
family: Some("Adams".into()),
suffix: None,
};
assert_eq!(p.to_string(), "John Robert Adams".to_string());
let p = PersonName::builder().with_middle("Robert").build();
assert_eq!(p.to_string(), "Robert".to_string());
}
#[test]
fn person_name_from_slice() {
assert_eq!(
PersonName::from_text("^^Robert"),
PersonName::builder().with_middle("Robert").build()
);
assert_eq!(
PersonName::from_text("^^^Rev."),
PersonName::builder().with_prefix("Rev.").build()
);
assert_eq!(
PersonName::from_text("^^^^B.A. M.Div."),
PersonName::builder().with_suffix("B.A. M.Div.").build()
);
assert_eq!(
PersonName::from_text("^^Robert"),
PersonName::builder().with_middle("Robert").build()
);
assert_eq!(
PersonName::from_text("^John"),
PersonName::builder().with_given("John").build()
);
assert_eq!(
PersonName::from_text("Adams"),
PersonName::builder().with_family("Adams").build()
);
assert_eq!(
PersonName::from_text("Adams^^^^B.A. M.Div."),
PersonName::builder()
.with_family("Adams")
.with_suffix("B.A. M.Div.")
.build()
);
assert_eq!(
PersonName::from_text("Adams^^Robert^^B.A. M.Div."),
PersonName {
prefix: None,
given: None,
middle: Some("Robert".into()),
family: Some("Adams".into()),
suffix: Some("B.A. M.Div.".into()),
}
);
assert_eq!(
PersonName::from_text("Adams^John^Robert^Rev.^B.A. M.Div."),
PersonName {
prefix: Some("Rev.".into()),
given: Some("John".into()),
middle: Some("Robert".into()),
family: Some("Adams".into()),
suffix: Some("B.A. M.Div.".into()),
}
);
assert_eq!(
PersonName::from_text("Adams^ "),
PersonName {
prefix: None,
given: None,
middle: None,
family: Some("Adams".into()),
suffix: None,
}
);
}
}