pub extra_config: Vec<PathBuf>,
}
+#[ext]
+impl<'s> Option<&'s str> {
+ #[throws(AE)]
+ fn value(self) -> &'s str {
+ self.ok_or_else(|| anyhow!("value needed"))?
+ }
+}
+
pub struct Secret(pub String);
impl Parseable for Secret {
#[throws(AE)]
fn parse(s: Option<&str>) -> Self {
- let s = s.ok_or_else(|| anyhow!("value needed"))?;
+ let s = s.value()?;
if s.is_empty() { throw!(anyhow!("secret value cannot be empty")) }
Secret(s.into())
}
impl Parseable for Duration {
#[throws(AE)]
fn parse(s: Option<&str>) -> Duration {
- let s = s.as_ref().ok_or_else(|| anyhow!("value needed"))?;
+ let s = s.value()?;
if let Ok(u64) = s.parse() { return Duration::from_secs(u64) }
throw!(anyhow!("xxx parse with humantime"))
}
macro_rules! parseable_from_str { ($t:ty $(, $def:expr)? ) => {
impl Parseable for $t {
#[throws(AE)]
- fn parse(s: Option<&str>) -> $t {
- let s = s.as_ref().ok_or_else(|| anyhow!("value needed"))?;
- s.parse()?
- }
- $(
- #[throws(AE)] fn default() -> Self { $def }
- )?
+ fn parse(s: Option<&str>) -> $t { s.value()?.parse()? }
+ $( #[throws(AE)] fn default() -> Self { $def } )?
}
} }
parseable_from_str!{u16, default() }
impl<T:Parseable> Parseable for Vec<T> {
#[throws(AE)]
fn parse(s: Option<&str>) -> Vec<T> {
- let s = s.as_ref().ok_or_else(|| anyhow!("value needed"))?;
- s.split_ascii_whitespace()
+ s.value()?
+ .split_ascii_whitespace()
.map(|s| Parseable::parse(Some(s)))
.collect::<Result<Vec<_>,_>>()?
}
"server",
[ &SectionName::Common, &self.special_server_section ].iter().cloned()
) {
- Some(RawVal { val: Some(ref got),.. }) => got,
- Some(RawVal { val: None,.. }) => throw!(anyhow!("value needed")),
+ Some(raw) => raw.val.as_deref().value()?,
None => SPECIAL_SERVER_SECTION,
};
ServerName(raw.into())