diff --git a/crates/wiggle/generate/src/config.rs b/crates/wiggle/generate/src/config.rs index 6eecf28c96..735cb92546 100644 --- a/crates/wiggle/generate/src/config.rs +++ b/crates/wiggle/generate/src/config.rs @@ -18,6 +18,7 @@ pub struct Config { pub witx: WitxConf, pub ctx: CtxConf, pub errors: ErrorConf, + pub logging: LoggingConf, } #[derive(Debug, Clone)] @@ -25,25 +26,45 @@ pub enum ConfigField { Witx(WitxConf), Ctx(CtxConf), Error(ErrorConf), + Logging(LoggingConf), } -impl ConfigField { - pub fn parse_pair(ident: &str, value: ParseStream, err_loc: Span) -> Result { - match ident { - "witx" => Ok(ConfigField::Witx(WitxConf::Paths(value.parse()?))), - "witx_literal" => Ok(ConfigField::Witx(WitxConf::Literal(value.parse()?))), - "ctx" => Ok(ConfigField::Ctx(value.parse()?)), - "errors" => Ok(ConfigField::Error(value.parse()?)), - _ => Err(Error::new(err_loc, "expected `witx`, `ctx`, or `errors`")), - } - } +mod kw { + syn::custom_keyword!(witx); + syn::custom_keyword!(witx_literal); + syn::custom_keyword!(ctx); + syn::custom_keyword!(logging); + syn::custom_keyword!(errors); + syn::custom_keyword!(log); + syn::custom_keyword!(tracing); } impl Parse for ConfigField { fn parse(input: ParseStream) -> Result { - let id: Ident = input.parse()?; - let _colon: Token![:] = input.parse()?; - Self::parse_pair(id.to_string().as_ref(), input, id.span()) + let lookahead = input.lookahead1(); + if lookahead.peek(kw::witx) { + input.parse::()?; + input.parse::()?; + Ok(ConfigField::Witx(WitxConf::Paths(input.parse()?))) + } else if lookahead.peek(kw::witx_literal) { + input.parse::()?; + input.parse::()?; + Ok(ConfigField::Witx(WitxConf::Literal(input.parse()?))) + } else if lookahead.peek(kw::ctx) { + input.parse::()?; + input.parse::()?; + Ok(ConfigField::Ctx(input.parse()?)) + } else if lookahead.peek(kw::logging) { + input.parse::()?; + input.parse::()?; + Ok(ConfigField::Logging(input.parse()?)) + } else if lookahead.peek(kw::errors) { + input.parse::()?; + input.parse::()?; + Ok(ConfigField::Error(input.parse()?)) + } else { + Err(lookahead.error()) + } } } @@ -52,6 +73,7 @@ impl Config { let mut witx = None; let mut ctx = None; let mut errors = None; + let mut logging = None; for f in fields { match f { ConfigField::Witx(c) => { @@ -72,6 +94,12 @@ impl Config { } errors = Some(c); } + ConfigField::Logging(c) => { + if logging.is_some() { + return Err(Error::new(err_loc, "duplicate `logging` field")); + } + logging = Some(c); + } } } Ok(Config { @@ -82,6 +110,7 @@ impl Config { .take() .ok_or_else(|| Error::new(err_loc, "`ctx` field required"))?, errors: errors.take().unwrap_or_default(), + logging: logging.take().unwrap_or_default(), }) } @@ -290,3 +319,34 @@ impl Parse for ErrorConfField { }) } } + +/// Configure logging statements in generated code +pub enum LoggingConf { + Log { cfg_feature: Option }, + Tracing, +} + +impl Default for LoggingConf { + fn default() -> Self { + // For compatibility with existing code. We should probably revise this later. + LoggingConf::Log { + cfg_feature: Some("trace_log".to_owned()), + } + } +} + +impl Parse for LoggingConf { + fn parse(input: ParseStream) -> Result { + let lookahead = input.lookahead1(); + if lookahead.peek(kw::log) { + input.parse::()?; + // TODO: syntax so the user can specify their own cfg_feature guard here. + Ok(LoggingConf::Log { cfg_feature: None }) + } else if lookahead.peek(kw::tracing) { + input.parse::()?; + Ok(LoggingConf::Tracing) + } else { + Err(lookahead.error()) + } + } +}