From 9f8090847c97c2f44a2db8fcd8310624e9ebac27 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sun, 25 Sep 2022 19:44:52 +0100 Subject: [PATCH] config: inspectable config keys Signed-off-by: Ian Jackson --- macros/macros.rs | 12 ++++++++++++ src/config.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ src/prelude.rs | 4 +++- src/types.rs | 2 ++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/macros/macros.rs b/macros/macros.rs index 1eaa758..1a158a7 100644 --- a/macros/macros.rs +++ b/macros/macros.rs @@ -79,6 +79,7 @@ pub fn resolve(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let mut output = vec![]; let mut global_fields = vec![]; let mut global_assignments = vec![]; + let mut inspects = vec![]; for field in &fields.named { //dbg!(field); let fname = &field.ident.as_ref().unwrap(); @@ -146,6 +147,9 @@ pub fn resolve(input: proc_macro::TokenStream) -> proc_macro::TokenStream { output.push(quote!{ #fname: rctx. #method ( #fname_lit, #skl )?, }); + inspects.push(quote!{ + #fname_lit => &self.#fname, + }); //eprintln!("{:?} method={:?} skl={:?}", field.ident, method, skl); } //dbg!(&output); @@ -165,6 +169,14 @@ pub fn resolve(input: proc_macro::TokenStream) -> proc_macro::TokenStream { #( #output )* }) } + + pub fn inspect_key(&self, field: &'_ str) + -> Option<&dyn InspectableConfigValue> { + Some(match field { + #( #inspects )* + _ => return None, + }) + } } #[derive(Debug)] diff --git a/src/config.rs b/src/config.rs index 648baf3..f3dfe49 100644 --- a/src/config.rs +++ b/src/config.rs @@ -88,6 +88,54 @@ pub struct Opts { /// Additional config files or dirs, which can override the others #[structopt(long, multiple=true, number_of_values=1)] pub extra_config: Vec, + + /// Print configuration rather than running + #[structopt(long)] + pub print_config: bool, +} + +pub trait InspectableConfigValue { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result; +} +#[macro_export] +macro_rules! impl_inspectable_config_value { + { $t:ty as $trait:path } => { + impl InspectableConfigValue for $t { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + ::fmt(self, f) + } + } + }; + + { Vec<$t:ty> } => { + impl InspectableConfigValue for Vec<$t> { + #[throws(fmt::Error)] + fn fmt(&self, f: &mut fmt::Formatter) { + let mut first = Some(()); + for v in self.iter() { + if first.take().is_none() { write!(f, " ")?; } + InspectableConfigValue::fmt(v, f)?; + } + } + } + }; +} + +impl_inspectable_config_value!{ String as Display } +impl_inspectable_config_value!{ u16 as Display } +impl_inspectable_config_value!{ u32 as Display } +impl_inspectable_config_value!{ hyper::Uri as Display } + +impl_inspectable_config_value!{ IpAddr as Display } +impl_inspectable_config_value!{ ipnet::IpNet as Display } +impl_inspectable_config_value!{ Vec } +impl_inspectable_config_value!{ Vec } + +impl InspectableConfigValue for Duration { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let v = self.as_secs_f64(); + Display::fmt(&v, f) + } } #[ext(pub)] @@ -119,6 +167,7 @@ impl Debug for Secret { #[throws(fmt::Error)] fn fmt(&self, f: &mut fmt::Formatter) { write!(f, "Secret(***)")? } } +impl_inspectable_config_value!{ Secret as Debug } #[derive(Debug,Clone,Hash,Eq,PartialEq)] pub enum SectionName { diff --git a/src/prelude.rs b/src/prelude.rs index 0ca0ec1..35e012e 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -55,7 +55,9 @@ pub use eyre::eyre as anyhow; pub use eyre::WrapErr; pub use eyre::Error as AE; -pub use crate::config::{self, InstanceConfig, u32Ext as _}; +pub use crate::config::{self, InspectableConfigValue, InstanceConfig}; +pub use crate::config::u32Ext as _; +pub use crate::impl_inspectable_config_value; pub use crate::ini; pub use crate::ipif::Ipif; pub use crate::multipart::{self, PartName, MetadataFieldIterator}; diff --git a/src/types.rs b/src/types.rs index 1f55aa6..c5b4737 100644 --- a/src/types.rs +++ b/src/types.rs @@ -74,3 +74,5 @@ impl Display for LinkName { write!(f, "[{} {}]", &self.server, &self.client)?; } } + +impl_inspectable_config_value!{ LinkName as Display } -- 2.30.2