Skip to main content

compose_yml/v2/
aliased_name.rs

1use super::common::*;
2
3/// The name of an external resource, and an optional local alias to which
4/// it is mapped inside a container.
5#[derive(Debug, Clone, Eq, PartialEq)]
6pub struct AliasedName {
7    /// The name of the external resouce outside the container.
8    name: String,
9
10    /// An optional alias for the external resource inside the container.
11    /// If not present, the external name should be used.
12    alias: Option<String>,
13}
14
15impl AliasedName {
16    /// Create a new AliasedName from a name and option alias.
17    pub fn new(name: &str, alias: Option<&str>) -> Result<AliasedName> {
18        let result = AliasedName {
19            name: name.to_owned(),
20            alias: alias.map(|v| v.to_owned()),
21        };
22        result.validate()?;
23        Ok(result)
24    }
25
26    /// (Internal.) Validate an aliased name is safely serializeable.
27    fn validate(&self) -> Result<()> {
28        let bad_name = self.name.contains(':');
29        let bad_alias = self
30            .alias
31            .as_ref()
32            .map(|a| a.contains(':'))
33            .unwrap_or(false);
34        if bad_name || bad_alias {
35            let val = format!("{:?}", &self);
36            return Err(Error::invalid_value("aliased name", val));
37        }
38        Ok(())
39    }
40}
41
42impl_interpolatable_value!(AliasedName);
43
44impl fmt::Display for AliasedName {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        match &self.alias {
47            Some(alias) => write!(f, "{}:{}", &self.name, alias),
48            None => write!(f, "{}", &self.name),
49        }
50    }
51}
52
53impl FromStr for AliasedName {
54    type Err = Error;
55
56    fn from_str(s: &str) -> Result<Self> {
57        lazy_static! {
58            static ref ALIASED_NAME: Regex =
59                Regex::new("^([^:]+)(?::([^:]+))?$").unwrap();
60        }
61        let caps = ALIASED_NAME
62            .captures(s)
63            .ok_or_else(|| Error::invalid_value("aliased name", s))?;
64        Ok(AliasedName {
65            name: caps.get(1).unwrap().as_str().to_owned(),
66            alias: caps.get(2).map(|v| v.as_str().to_owned()),
67        })
68    }
69}
70
71#[test]
72fn aliased_name_can_be_converted_to_and_from_a_string() {
73    assert_eq!(
74        AliasedName::from_str("foo").unwrap(),
75        AliasedName {
76            name: "foo".to_owned(),
77            alias: None
78        }
79    );
80    assert_eq!(
81        AliasedName::from_str("foo:bar").unwrap(),
82        AliasedName {
83            name: "foo".to_owned(),
84            alias: Some("bar".to_owned())
85        }
86    );
87    assert!(AliasedName::from_str("foo:bar:baz").is_err());
88
89    assert_eq!(AliasedName::new("foo", None).unwrap().to_string(), "foo");
90    assert_eq!(
91        AliasedName::new("foo", Some("bar")).unwrap().to_string(),
92        "foo:bar"
93    );
94}