/// Generates config resolver method
///
+/// Each field ends up having an SKL and a method.
+/// The method actually looks up the value in a particular link context.
+/// SKL is passed to the method, which usually uses it to decide which
+/// sections to look in. But it is also used by general validation,
+/// unconditionally, to reject settings in the wrong section.
+///
/// Atrributes:
///
/// * `limited`, `server`, `client`: cooked sets of settings;
/// ```no_run
/// impl<'c> ResolveContext<'c> {
///
+/// // SKL here is used by SectionKindList::contains()
/// const FIELDS: &'static [(&'static str, SectionKindList)] = &[ ... ];
///
/// #[throws(AE)]
/// fn resolve_instance(&self) -> InstanceConfig {
/// InstanceConfig {
/// ...
-/// max_batch_down: self.limited("max_batch_down")?,
+/// // SKL here is usually passed to first_of, but the method
+/// // can do something more special.
+/// max_batch_down: self.limited("max_batch_down", SKL::PerClient)?,
/// ...
/// }
/// }
});
//dbg!(&method);
output.push(quote!{
- #fname: rctx. #method ( #fname_lit )?,
+ #fname: rctx. #method ( #fname_lit, #skl )?,
});
//eprintln!("{:?} method={:?} skl={:?}", field.ident, method, skl);
}
}
#[throws(AE)]
- pub fn ordinary<T>(&self, key: &'static str) -> T
+ pub fn ordinary<T>(&self, key: &'static str, skl: SKL) -> T
where T: Parseable
{
- match self.first_of(key, SKL::PerClient)? {
+ match self.first_of(key, skl)? {
Some(y) => y,
None => Parseable::default_for_key(key)?,
}
}
#[throws(AE)]
- pub fn limited<T>(&self, key: &'static str) -> T
+ pub fn limited<T>(&self, key: &'static str, skl: SKL) -> T
where T: Parseable + Ord
{
- let val = self.ordinary(key)?;
+ assert_eq!(skl, SKL::Limited);
+ let val = self.ordinary(key, SKL::PerClient)?;
if let Some(limit) = self.first_of(key, SKL::Limits)? {
min(val, limit)
} else {
}
#[throws(AE)]
- pub fn client<T>(&self, key: &'static str) -> T
+ pub fn client<T>(&self, key: &'static str, skl: SKL) -> T
where T: Parseable + Default {
match self.end {
- LinkEnd::Client => self.ordinary(key)?,
+ LinkEnd::Client => self.ordinary(key, skl)?,
LinkEnd::Server => default(),
}
}
#[throws(AE)]
- pub fn server<T>(&self, key: &'static str) -> T
+ pub fn server<T>(&self, key: &'static str, skl: SKL) -> T
where T: Parseable + Default {
match self.end {
- LinkEnd::Server => self.ordinary(key)?,
+ LinkEnd::Server => self.ordinary(key, skl)?,
LinkEnd::Client => default(),
}
}
#[throws(AE)]
- pub fn computed<T>(&self, _key: &'static str) -> T
+ pub fn computed<T>(&self, _key: &'static str, _skl: SKL) -> T
where T: Default
{
default()
}
#[throws(AE)]
- pub fn special_ipif(&self, key: &'static str) -> String {
+ pub fn special_ipif(&self, key: &'static str, skl: SKL) -> String {
+ assert_eq!(skl, SKL::PerClient); // we tolerate it in per-client sections
match self.end {
- LinkEnd::Client => self.ordinary(key)?,
+ LinkEnd::Client => self.ordinary(key, SKL::PerClient)?,
LinkEnd::Server => {
self.first_of(key, SKL::Global)?
.unwrap_or_default()
}
#[throws(AE)]
- pub fn special_link(&self, _key: &'static str) -> LinkName {
+ pub fn special_link(&self, _key: &'static str, _skl: SKL) -> LinkName {
self.link.clone()
}
}