chiark / gitweb /
config, centralise "value needed"
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 24 Jul 2021 12:49:10 +0000 (13:49 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 24 Jul 2021 12:49:10 +0000 (13:49 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/config.rs

index 75c3e250f973d4222993535c2ff102e62bde677c..3eae89d084d916fcb3291164ff59663fb97fb6e1 100644 (file)
@@ -21,11 +21,19 @@ pub struct Opts {
   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())
   }
@@ -294,7 +302,7 @@ trait Parseable: Sized {
 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"))
   }
@@ -302,13 +310,8 @@ impl Parseable for Duration {
 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() }
@@ -321,8 +324,8 @@ parseable_from_str!{Uri, 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<_>,_>>()?
   }
@@ -466,8 +469,7 @@ impl<'c> ResolveContext<'c> {
       "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())