#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ServiceOrContainer {
Service(String),
Container(String),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VolumesFrom {
pub source: ServiceOrContainer,
pub permissions: VolumePermissions,
}
impl_interpolatable_value!(VolumesFrom);
impl fmt::Display for VolumesFrom {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match &self.source {
&ServiceOrContainer::Service(ref name) =>
try!(write!(f, "{}", name)),
&ServiceOrContainer::Container(ref name) =>
try!(write!(f, "container:{}", name)),
}
if self.permissions != Default::default() {
try!(write!(f, ":{}", self.permissions))
}
Ok(())
}
}
impl FromStr for VolumesFrom {
type Err = InvalidValueError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
lazy_static! {
static ref FROM: Regex =
Regex::new("^(container:)?([^:]+)(?::([^:]+))?$").unwrap();
}
let caps = try!(FROM.captures(s).ok_or_else(|| {
InvalidValueError::new("volumes_from", s)
}));
let name = caps.at(2).unwrap().to_owned();
let source =
if caps.at(1).is_some() {
ServiceOrContainer::Container(name)
} else {
ServiceOrContainer::Service(name)
};
let permissions =
match caps.at(3) {
None => Default::default(),
Some(permstr) => try!(FromStr::from_str(permstr)),
};
Ok(VolumesFrom {
source: source,
permissions: permissions,
})
}
}
#[test]
fn volumes_from_should_have_a_string_representation() {
let vf1 = VolumesFrom {
source: ServiceOrContainer::Service("foo".to_owned()),
permissions: Default::default(),
};
let vf2 = VolumesFrom {
source: ServiceOrContainer::Container("foo".to_owned()),
permissions: VolumePermissions::ReadOnly,
};
let pairs = vec!(
(vf1, "foo"),
(vf2, "container:foo:ro"),
);
for (vf, s) in pairs {
assert_eq!(vf.to_string(), s);
assert_eq!(vf, VolumesFrom::from_str(s).unwrap());
}
}