#[derive(Debug, Clone, Eq, PartialEq)]
pub struct AliasedName {
name: String,
alias: Option<String>,
}
impl AliasedName {
pub fn new(name: &str, alias: Option<&str>) ->
Result<AliasedName, InvalidValueError>
{
let result = AliasedName {
name: name.to_owned(),
alias: alias.map(|v| v.to_owned()),
};
try!(result.validate());
Ok(result)
}
fn validate(&self) -> Result<(), InvalidValueError> {
let bad_name = self.name.contains(":");
let bad_alias = self.alias.as_ref()
.map(|a| a.contains(":")).unwrap_or(false);
if bad_name || bad_alias {
let val = format!("{:?}", &self);
return Err(InvalidValueError::new("aliased name", &val));
}
Ok(())
}
}
impl_interpolatable_value!(AliasedName);
impl fmt::Display for AliasedName {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match &self.alias {
&Some(ref alias) => write!(f, "{}:{}", &self.name, alias),
&None => write!(f, "{}", &self.name),
}
}
}
impl FromStr for AliasedName {
type Err = InvalidValueError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
lazy_static! {
static ref ALIASED_NAME: Regex =
Regex::new("^([^:]+)(?::([^:]+))?$").unwrap();
}
let caps = try!(ALIASED_NAME.captures(s).ok_or_else(|| {
InvalidValueError::new("aliased name", s)
}));
Ok(AliasedName {
name: caps.at(1).unwrap().to_owned(),
alias: caps.at(2).map(|v| v.to_owned()),
})
}
}
#[test]
fn aliased_name_can_be_converted_to_and_from_a_string() {
assert_eq!(AliasedName::from_str("foo").unwrap(),
AliasedName { name: "foo".to_owned(), alias: None });
assert_eq!(AliasedName::from_str("foo:bar").unwrap(),
AliasedName { name: "foo".to_owned(),
alias: Some("bar".to_owned()) });
assert!(AliasedName::from_str("foo:bar:baz").is_err());
assert_eq!(AliasedName::new("foo", None).unwrap().to_string(),
"foo");
assert_eq!(AliasedName::new("foo", Some("bar")).unwrap().to_string(),
"foo:bar");
}