Replace our bespoke proc_macro with a derive-deftly macro.
The macro is based on one written for derive-adhoc 0.0.1, so could do
with a bit of updating.
I've inspeccted the changes to the generated output with a semi-manual
diff. The only significant changes were changes to
`impl InspectableConfigAuto for InstanceConfig`, as follows:
> + "link" => &self.link,
This is case is handled by the manually-written
`impl InspectableConfig for InstanceConfig` so never reaches
the derived impl. But it is identical.
> + "max_batch_up" => &self.max_batch_up,
This seems to have been an omission in the previous code.
So the addition seems good.
> "max_clock_skew" => &self.max_clock_skew,
> - "max_clock_skew" => &self.max_clock_skew,
> - "ifname_server" => &self.ifname_server,
> "ifname_server" => &self.ifname_server,
This is the removal of two duplicates, which arose from the odd code
structure in the previous code, which does code gen for inspect_key
once per attribute, rather than once per field.
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
"powerfmt",
]
+[[package]]
+name = "derive-deftly"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0015cb20a284ec944852820598af3aef6309ea8dc317a0304441272ed620f196"
+dependencies = [
+ "derive-deftly-macros",
+ "heck",
+]
+
+[[package]]
+name = "derive-deftly-macros"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b48e8e38a4aa565da767322b5ca55fb0f8347983c5bc7f7647db069405420479"
+dependencies = [
+ "heck",
+ "indexmap",
+ "itertools",
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "sha3",
+ "strum",
+ "syn 2.0.100",
+ "void",
+]
+
[[package]]
name = "digest"
version = "0.10.7"
"base64",
"cfg-if",
"clap",
+ "derive-deftly",
"easy-ext",
"educe",
"either",
"wasm-bindgen",
]
+[[package]]
+name = "keccak"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654"
+dependencies = [
+ "cpufeatures",
+]
+
[[package]]
name = "lazy-regex"
version = "3.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+[[package]]
+name = "proc-macro-crate"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
+dependencies = [
+ "toml_edit",
+]
+
[[package]]
name = "proc-macro2"
version = "1.0.94"
"digest",
]
+[[package]]
+name = "sha3"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
+dependencies = [
+ "digest",
+ "keccak",
+]
+
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+[[package]]
+name = "strum"
+version = "0.27.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32"
+dependencies = [
+ "strum_macros",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.27.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 2.0.100",
+]
+
[[package]]
name = "subtle"
version = "2.6.1"
"tokio",
]
+[[package]]
+name = "toml_datetime"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
+
+[[package]]
+name = "toml_edit"
+version = "0.22.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
+dependencies = [
+ "indexmap",
+ "toml_datetime",
+ "winnow",
+]
+
[[package]]
name = "tower"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
+[[package]]
+name = "winnow"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"
"heck",
"proc-macro2",
"quote",
- "syn 2.0.52",
+ "syn 2.0.53",
]
[[package]]
"generic-array",
]
+[[package]]
+name = "derive-deftly"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39502f680ea10252d02b2809e56239acb3aa68d3659c0e0171ade79c04c48086"
+dependencies = [
+ "derive-deftly-macros",
+ "heck",
+]
+
+[[package]]
+name = "derive-deftly-macros"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c964673dd1023a358bbc0090f6761aee64dddbd21bc7fa91853e92201110e8f"
+dependencies = [
+ "heck",
+ "indexmap 1.8.0",
+ "itertools",
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "sha3",
+ "strum",
+ "syn 2.0.53",
+ "void",
+]
+
[[package]]
name = "digest"
version = "0.10.2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.52",
+ "syn 2.0.53",
]
[[package]]
"futures-sink",
"futures-util",
"http",
- "indexmap",
+ "indexmap 2.0.0",
"slab",
"tokio",
"tokio-util",
"tracing",
]
+[[package]]
+name = "hashbrown"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "362385356d610bd1e5a408ddf8d022041774b683f345a1d2cfcb4f60f8ae2db5"
+
[[package]]
name = "hashbrown"
version = "0.14.0"
"base64 0.21.0",
"cfg-if 1.0.0",
"clap",
+ "derive-deftly",
"easy-ext",
"educe",
"either",
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0bd112d44d9d870a6819eb505d04dd92b5e4d94bb8c304924a0872ae7016fb5"
+[[package]]
+name = "indexmap"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
+dependencies = [
+ "autocfg 1.1.0",
+ "hashbrown 0.11.0",
+]
+
[[package]]
name = "indexmap"
version = "2.0.0"
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
dependencies = [
"equivalent",
- "hashbrown",
+ "hashbrown 0.14.0",
]
[[package]]
"wasm-bindgen",
]
+[[package]]
+name = "keccak"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7"
+
[[package]]
name = "lazy-regex"
version = "2.4.0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.52",
+ "syn 2.0.53",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe1c37e6347ad1a8351171bee25a92342401f8cd550f76e153724e765ac76bca"
+[[package]]
+name = "proc-macro-crate"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
+dependencies = [
+ "thiserror",
+ "toml",
+]
+
[[package]]
name = "proc-macro2"
version = "1.0.75"
"untrusted",
]
+[[package]]
+name = "rustversion"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c48f91977f4ef3be5358c15d131d3f663f6b4d7a112555bf3bf52ad23b6659e5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.103",
+]
+
[[package]]
name = "ryu"
version = "1.0.0"
"digest",
]
+[[package]]
+name = "sha3"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31f935e31cf406e8c0e96c2815a5516181b7004ae8c5f296293221e9b1e356bd"
+dependencies = [
+ "digest",
+ "keccak",
+]
+
[[package]]
name = "signal-hook-registry"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+[[package]]
+name = "strum"
+version = "0.24.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e96acfc1b70604b8b2f1ffa4c57e59176c7dbb05d556c71ecd2f5498a1dee7f8"
+dependencies = [
+ "strum_macros",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.24.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 1.0.103",
+]
+
[[package]]
name = "subtle"
version = "2.5.0"
[[package]]
name = "syn"
-version = "2.0.52"
+version = "2.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
+checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
dependencies = [
"proc-macro2",
"quote",
[[package]]
name = "thiserror"
-version = "1.0.2"
+version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79067843a369b7df0391d33d48636936ee91aa6d6370931eebe1278e6f88a723"
+checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.2"
+version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dc6215837a07b345fd86880601a9c55bb5974e0cec507c48bbd3aaa006559a9"
+checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
dependencies = [
"proc-macro2",
"quote",
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.52",
+ "syn 2.0.53",
]
[[package]]
"tracing",
]
+[[package]]
+name = "toml"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a54ae44b0b2c443e7ef6dd3be16a776bae4daa40684f81e15126bc04e7747308"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "tower-service"
version = "0.3.0"
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.52",
+ "syn 2.0.53",
"wasm-bindgen-shared",
]
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.52",
+ "syn 2.0.53",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[dependencies]
+derive-deftly = "1"
hippotat-macros = { version = "=1.2.1", path = "macros" }
backtrace = "0.3.74"
librust-base64-dev (>= 0.21~) <!upstream-cargo>,
librust-cfg-if-dev (>= 1~) <!upstream-cargo>,
librust-clap+derive-dev (>= 4~) <!upstream-cargo>,
+ librust-derive-deftly-dev (>= 1~) <!upstream-cargo>,
librust-easy-ext-dev (>= 1~) <!upstream-cargo>,
librust-educe-dev (>= 0.4.1~) <!upstream-cargo>,
librust-either-dev (>= 1.5.1~) <!upstream-cargo>,
#![allow(clippy::map_flatten)]
#![allow(clippy::single_char_pattern)]
-use syn::{parse_macro_input, parse_quote};
-use syn::{Data, DataStruct, DeriveInput, LitStr, Meta, NestedMeta};
-use quote::{quote, quote_spanned, ToTokens};
-use proc_macro2::{Literal, TokenStream};
-
-use std::cell::RefCell;
-
-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;
-/// default `SKL` is `PerClient` except for `limited`
-/// * `global` and `per_client`: set the SKL.
-/// * `special(method, SKL)`
-///
-/// Generated code
-///
-/// ```rust,ignore
-/// 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 {
-/// ...
-/// // 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)?,
-/// ...
-/// }
-/// }
-/// }
-///
-/// pub struct InstanceConfigCommon { ... }
-/// impl InstanceConfigCommon {
-/// pub fn from(l: &[InstanceConfig]) { InstanceConfigCommon {
-/// field: <Type as ResolveGlobal>::resolve(l.iter().map(|e| &e.field)),
-/// ...
-/// } }
-/// }
-/// ```
-#[proc_macro_derive(ResolveConfig, attributes(
- limited, server, client, computed, special,
- per_client, global,
-))]
-pub fn resolve(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
- let input = parse_macro_input!(input as DeriveInput);
-
- let (fields, top_ident) = match input {
- DeriveInput {
- ref ident,
- data: Data::Struct(DataStruct {
- fields: syn::Fields::Named(ref f),
- ..
- }),
- ..
- } => (f, ident),
- _ => panic!(),
- };
-
- let target = &input.ident;
-
- let mut names = vec![];
- let mut output = vec![];
- let mut global_fields = vec![];
- let mut global_assignments = vec![];
- let mut g_inspects = vec![];
- let mut t_inspects = vec![];
- for field in &fields.named {
- //dbg!(field);
- let fname = &field.ident.as_ref().unwrap();
- let fname_string = fname.to_string();
- let fname_lit = Literal::string( &fname_string );
- let ty = &field.ty;
- let fname_span = fname.span();
- let skl = RefCell::new(None);
- let set_skl = |new| {
- let mut skl = skl.borrow_mut();
- if let Some(old) = &*skl { panic!("dup SKL {} and {} for field {}",
- old, new, &fname); }
- *skl = Some(new);
- };
- let mut method = quote_spanned!{fname_span=> ordinary };
- for attr in &field.attrs {
- let atspan = attr.path.segments.last().unwrap().ident.span();
- if attr.tokens.is_empty() {
- let inspect = quote!{
- #fname_lit => &self.#fname,
- };
- t_inspects.push(inspect.clone());
- if attr.path == parse_quote!{ per_client } {
- set_skl(quote_spanned!{fname_span=> SectionKindList::PerClient });
- continue;
- } else if attr.path == parse_quote!{ global } {
- set_skl(quote_spanned!{fname_span=> SectionKindList::Global });
- global_fields.push(syn::Field {
- attrs: vec![],
- ..field.clone()
- });
- global_assignments.push(quote_spanned!(fname_span=>
- #fname: <#ty as ResolveGlobal>::resolve
- (l.iter().map(|e| &e.#fname)),
- ));
- g_inspects.push(inspect);
- continue;
- }
- method = attr.path.to_token_stream();
- if attr.path == parse_quote!{ limited } {
- set_skl(quote_spanned!{atspan=> SectionKindList::Limited });
- } else if attr.path == parse_quote!{ client } {
- set_skl(quote_spanned!{atspan=> SectionKindList::PerClient });
- } else if attr.path == parse_quote!{ computed } {
- set_skl(quote_spanned!{atspan=> SectionKindList::None });
- }
- } else if attr.path == parse_quote!{ special } {
- let meta = match attr.parse_meta().unwrap() {
- Meta::List(list) => list,
- _ => panic!(),
- };
- let (tmethod, tskl) = meta.nested.iter().collect_tuple().unwrap();
- fn get_path(meta: &NestedMeta) -> TokenStream {
- match meta {
- NestedMeta::Meta(Meta::Path(ref path)) => path.to_token_stream(),
- _ => panic!(),
- }
- }
- method = get_path(tmethod);
- *skl.borrow_mut() = Some(get_path(tskl));
- }
- }
- let skl = skl.into_inner()
- .expect(&format!("SKL not specified! (field {})!", fname));
-
- names.push(quote!{
- (#fname_lit, #skl),
- });
- //dbg!(&method);
- output.push(quote!{
- #fname: rctx. #method ( #fname_lit, #skl )?,
- });
- //eprintln!("{:?} method={:?} skl={:?}", field.ident, method, skl);
- }
- //dbg!(&output);
-
- let global = syn::Ident::new(&format!("{}Global", top_ident),
- top_ident.span());
-
- let mk_inspects = |self_, inspects: Vec<_>| quote! {
- impl InspectableConfigAuto for #self_ {
- fn inspect_key_auto(&self, field: &'_ str)
- -> Option<&dyn InspectableConfigValue> {
- Some(match field {
- #( #inspects )*
- _ => return None,
- })
- }
- }
- };
- let g_inspects = mk_inspects(&global, g_inspects);
- let t_inspects = mk_inspects(&target, t_inspects);
-
- let output = quote! {
- impl #target {
- const FIELDS: &'static [(&'static str, SectionKindList)]
- = &[ #( #names )* ];
-
- fn resolve_instance(rctx: &ResolveContext)
- -> ::std::result::Result<#target, anyhow::Error>
- {
- ::std::result::Result::Ok(#target {
- #( #output )*
- })
- }
- }
-
- #t_inspects
-
- #[derive(Debug)]
- pub struct #global {
- #( #global_fields ),*
- }
-
- impl #global {
- pub fn from(l: &[#top_ident]) -> #global { #global {
- #( #global_assignments )*
- } }
- }
-
- #g_inspects
- };
-
- //eprintln!("{}", &output);
- output.into()
-}
+use syn::LitStr;
+use quote::quote;
#[proc_macro]
pub fn into_crlfs(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
use crate::prelude::*;
-#[derive(hippotat_macros::ResolveConfig)]
#[derive(Debug,Clone)]
+#[derive(Deftly)]
+#[derive_deftly(InspectableConfigAuto, InstanceConfig)]
pub struct InstanceConfig {
// Exceptional settings
- #[special(special_link, SKL::None)] pub link: LinkName,
- #[per_client] pub secret: Secret,
- #[global] #[special(special_ipif, SKL::PerClient)] pub ipif: String,
+ #[deftly(special="link", skl="SKL::None")] pub link: LinkName,
+ #[deftly(per_client)] pub secret: Secret,
+ #[deftly(global, special="ipif", skl="SKL::PerClient")] pub ipif: String,
// Capped settings:
- #[limited] pub max_batch_down: u32,
- #[limited] pub max_queue_time: Duration,
- #[limited] pub http_timeout: Duration,
- #[limited] pub target_requests_outstanding: u32,
- #[special(special_max_up, SKL::Limited)] pub max_batch_up: u32,
+ #[deftly(limited)] pub max_batch_down: u32,
+ #[deftly(limited)] pub max_queue_time: Duration,
+ #[deftly(limited)] pub http_timeout: Duration,
+ #[deftly(limited)] pub target_requests_outstanding: u32,
+ #[deftly(special="max_up", skl="SKL::Limited")] pub max_batch_up: u32,
// Ordinary settings, used by both, not client-specifi:
- #[global] pub addrs: Vec<IpAddr>,
- #[global] pub vnetwork: Vec<IpNet>,
- #[global] pub vaddr: IpAddr,
- #[global] pub vrelay: IpAddr,
- #[global] pub port: u16,
- #[global] pub mtu: u32,
+ #[deftly(global)] pub addrs: Vec<IpAddr>,
+ #[deftly(global)] pub vnetwork: Vec<IpNet>,
+ #[deftly(global)] pub vaddr: IpAddr,
+ #[deftly(global)] pub vrelay: IpAddr,
+ #[deftly(global)] pub port: u16,
+ #[deftly(global)] pub mtu: u32,
// Ordinary settings, used by server only:
- #[server] #[per_client] pub max_clock_skew: Duration,
- #[server] #[global] pub ifname_server: String,
+ #[deftly(server, per_client)] pub max_clock_skew: Duration,
+ #[deftly(server, global)] pub ifname_server: String,
// Ordinary settings, used by client only:
- #[client] pub http_timeout_grace: Duration,
- #[client] pub max_requests_outstanding: u32,
- #[client] pub http_retry: Duration,
- #[client] pub success_report_interval: Duration,
- #[client] pub url: Url,
- #[client] pub vroutes: Vec<IpNet>,
- #[client] pub ifname_client: String,
+ #[deftly(client)] pub http_timeout_grace: Duration,
+ #[deftly(client)] pub max_requests_outstanding: u32,
+ #[deftly(client)] pub http_retry: Duration,
+ #[deftly(client)] pub success_report_interval: Duration,
+ #[deftly(client)] pub url: Url,
+ #[deftly(client)] pub vroutes: Vec<IpNet>,
+ #[deftly(client)] pub ifname_client: String,
// Computed, rather than looked up. Client only:
- #[computed] pub effective_http_timeout: Duration,
+ #[deftly(computed)] pub effective_http_timeout: Duration,
}
static DEFAULT_CONFIG: &str = r#"
--- /dev/null
+
+use crate::prelude::*;
+
+define_derive_deftly! {
+ /// Implements `InspectableConfigAuto`
+ InspectableConfigAuto for struct, expect items:
+
+ impl InspectableConfigAuto for $ttype {
+ fn inspect_key_auto(&self, field: &'_ str)
+ -> Option<&dyn InspectableConfigValue> {
+ Some(match field {
+ $(
+ stringify!($fname) => &self.$fname,
+ )
+ _ => return None,
+ })
+ }
+ }
+}
+
+define_derive_deftly! {
+ /// Generates config resolver method, only for `InstanceConfig`
+ ///
+ /// 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;
+ /// default `SKL` is `PerClient` except for `limited`
+ /// * `global` and `per_client`: set the SKL.
+ /// * `special(method, SKL)`
+ ///
+ /// Generated code
+ ///
+ /// ```rust,ignore
+ /// 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 {
+ /// ...
+ /// // 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)?,
+ /// ...
+ /// }
+ /// }
+ /// }
+ ///
+ /// pub struct InstanceConfigCommon { ... }
+ /// impl InstanceConfigCommon {
+ /// pub fn from(l: &[InstanceConfig]) { InstanceConfigCommon {
+ /// field: <Type as ResolveGlobal>::resolve(l.iter().map(|e| &e.field)),
+ /// ...
+ /// } }
+ /// }
+ /// ```
+
+ InstanceConfig expect items:
+
+ struct InstanceConfigSKLs { $(
+ $fname: SectionKindList,
+ ) }
+ const FIELD_SKLS: InstanceConfigSKLs = InstanceConfigSKLs {
+ $(
+ $fname: ${if fmeta(skl) {
+ ${fmeta(skl) as expr}
+ } else {
+ ${select1
+ fmeta( per_client ) { SKL::PerClient }
+ fmeta( client ) { SKL::PerClient }
+ fmeta( global ) { SKL::Global }
+ fmeta( limited ) { SKL::Limited }
+ fmeta( computed ) { SKL::None }
+ }
+ }}
+ ,
+ )
+ };
+
+ impl InstanceConfig {
+ const FIELDS : & 'static [(& 'static str, SectionKindList)] = &[ $(
+ (
+ stringify!($fname),
+ FIELD_SKLS.$fname,
+ ),
+ ) ];
+
+ #[throws(AE)]
+ fn resolve_instance(rctx: &ResolveContext) -> InstanceConfig {
+ InstanceConfig {
+ $(
+ $fname: rctx.
+ ${if fmeta(special) {
+ ${paste special_ ${fmeta(special)}}
+ } else {
+ ${select1
+ fmeta( server ) { server }
+ fmeta( client ) { client }
+ fmeta( limited ) { limited }
+ fmeta( computed ) { computed }
+ else { ordinary }
+ }
+ }}
+ (
+ stringify!($fname),
+ FIELD_SKLS.$fname,
+ )?,
+ )
+ }
+ }
+ }
+
+ #[derive(Debug)]
+ #[derive(Deftly)]
+ #[derive_deftly(InspectableConfigAuto)]
+ pub struct InstanceConfigGlobal {
+ $(
+ ${when fmeta(global)}
+ pub $fname: $ftype,
+ )
+ }
+
+ impl InstanceConfigGlobal {
+ pub fn from(l: &[InstanceConfig]) -> InstanceConfigGlobal {
+ InstanceConfigGlobal {
+ $(
+ ${when fmeta(global)}
+ $fname: <$ftype as ResolveGlobal>
+ ::resolve(l.iter().map(|e| &e.$fname)),
+ )
+ }
+ }
+ }
+}
pub mod prelude;
+#[macro_use]
+pub mod config_derive;
+
pub mod compat;
pub mod config;
pub mod ipif;
pub use std::task::Poll;
pub use std::time::{SystemTime, UNIX_EPOCH};
+pub use derive_deftly::{define_derive_deftly, Deftly};
pub use educe::Educe;
pub use either::Either;
pub use easy_ext::ext;