chiark / gitweb /
config: Pass SKL to all the method functions, and document semantics
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 7 Aug 2021 16:57:36 +0000 (17:57 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 7 Aug 2021 18:46:00 +0000 (19:46 +0100)
This will make it possible to use the same method for things with
different applicable sections.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
macros/macros.rs
src/config.rs

index ac1a497df43b2cd68bad8d0b566ddae0fb4f8ee6..64501be8d62f696554ea284e778b964620464547 100644 (file)
@@ -11,6 +11,12 @@ use itertools::Itertools;
 
 /// 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;
@@ -22,13 +28,16 @@ use itertools::Itertools;
 /// ```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)?,
 ///        ...
 ///      }
 ///   }
@@ -86,7 +95,7 @@ pub fn resolve(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
     });
     //dbg!(&method);
     output.push(quote!{
-      #fname: rctx. #method ( #fname_lit )?,
+      #fname: rctx. #method ( #fname_lit, #skl )?,
     });
     //eprintln!("{:?} method={:?} skl={:?}", field.ident, method, skl);
   }
index a364efce46b8d925584c93d4fe3e64762e15c020..6a5e6bf560a7a20d2d7fd8b43e2a922f1fbb1cff 100644 (file)
@@ -610,20 +610,21 @@ impl<'c> ResolveContext<'c> {
   }
 
   #[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 {
@@ -632,33 +633,34 @@ impl<'c> ResolveContext<'c> {
   }
 
   #[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()
@@ -667,7 +669,7 @@ impl<'c> ResolveContext<'c> {
   }
 
   #[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()
   }
 }