// Ordinary settings:
pub addrs: Vec<IpAddr>,
- pub vnetwork: Vec<CidrString>,
+//xxx pub vnetwork: Vec<CidrString>,
pub vaddr: Vec<IpAddr>,
pub vrelay: IpAddr,
pub port: u16,
#[client] pub max_batch_up: u32,
#[client] pub http_retry: Duration,
#[client] pub url: Uri,
- #[client] pub vroutes: Vec<CidrString>,
+//xxx #[client] pub vroutes: Vec<CidrString>,
}
#[derive(Debug,Clone,Hash,Eq,PartialEq)]
}
trait Parseable: Sized {
- fn parse(s: &Option<String>) -> Result<Self, AE>;
+ fn parse(s: Option<&str>) -> Result<Self, AE>;
+ fn default() -> Result<Self, AE> {
+ Err(anyhow!("setting must be specified"))
+ }
+ #[throws(AE)]
+ fn default_for_key(key: &str) -> Self {
+ Self::default().with_context(|| key.to_string())?
+ }
}
impl Parseable for Duration {
#[throws(AE)]
- fn parse(s: &Option<String>) -> Duration {
+ fn parse(s: Option<&str>) -> Duration {
let s = s.as_ref().ok_or_else(|| anyhow!("value needed"))?;
if let Ok(u64) = s.parse() { return Duration::from_secs(u64) }
throw!(anyhow!("xxx parse with humantime"))
}
}
-macro_rules! parseable_from_str { ($t:ty) => {
+macro_rules! parseable_from_str { ($t:ty $(, $def:expr)? ) => {
impl Parseable for $t {
#[throws(AE)]
- fn parse(s: &Option<String>) -> $t {
+ 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 }
+ )?
}
} }
-parseable_from_str!{u32}
-parseable_from_str!{IpAddr}
+parseable_from_str!{u16, default() }
+parseable_from_str!{u32, default() }
+parseable_from_str!{String, default() }
+parseable_from_str!{IpAddr, Ipv4Addr::UNSPECIFIED.into() }
+parseable_from_str!{Uri, default() }
impl<T:Parseable> Parseable for Vec<T> {
#[throws(AE)]
- fn parse(s: &Option<String>) -> Vec<T> {
+ fn parse(s: Option<&str>) -> Vec<T> {
let s = s.as_ref().ok_or_else(|| anyhow!("value needed"))?;
s.split_ascii_whitespace()
- .map(|s| s.parse())
- .collect::<Result<Vec<_>>>()?
+ .map(|s| Parseable::parse(Some(s)))
+ .collect::<Result<Vec<_>,_>>()?
}
}
match self.first_of_raw(key, sections) {
None => None,
Some(raw) => Some({
- Parseable::parse(&raw.val)
+ Parseable::parse(raw.val.as_deref())
.context(key)
// .with_context(|| format!(r#"in section "{}""#, §ion))
.dcontext(&raw.loc)?
#[throws(AE)]
pub fn ordinary<T>(&self, key: &'static str) -> T
- where T: Parseable + Default
+ where T: Parseable
{
- self.first_of(key, SKL::Ordinary)?
- .unwrap_or_default()
+ match self.first_of(key, SKL::Ordinary)? {
+ Some(y) => y,
+ None => Parseable::default_for_key(key)?,
+ }
}
#[throws(AE)]
pub fn limited<T>(&self, key: &'static str) -> T
- where T: Parseable + Default + Ord
+ where T: Parseable + Ord
{
let val = self.ordinary(key)?;
if let Some(limit) = self.first_of(key, SKL::Limits)? {
#[throws(AE)]
pub fn client<T>(&self, key: &'static str) -> T
- where T: Parseable + Default {
+ where T: Parseable {
match self.end {
LinkEnd::Client => self.ordinary(key)?,
- LinkEnd::Server => default(),
+ LinkEnd::Server => Parseable::default_for_key(key)?,
}
}
#[throws(AE)]
pub fn server<T>(&self, key: &'static str) -> T
- where T: Parseable + Default {
+ where T: Parseable {
match self.end {
LinkEnd::Server => self.ordinary(key)?,
- LinkEnd::Client => default(),
+ LinkEnd::Client => Parseable::default_for_key(key)?,
}
}