defmt-macros 1.1.1

defmt macros
Documentation
use defmt_parser::ParserMode;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, parse_quote};

use crate::{construct, function_like::log};

use self::args::Args;

mod args;

pub(crate) fn expand(args: TokenStream) -> TokenStream {
    let Args {
        formatter,
        log_args,
        ..
    } = parse_macro_input!(args as Args);

    let format_string = log_args.format_string.value();
    let fragments = match defmt_parser::parse(&format_string, ParserMode::Strict) {
        Ok(args) => args,
        Err(e) => {
            return syn::Error::new(log_args.format_string.span(), format!("{}", e))
                .into_compile_error()
                .into()
        }
    };

    let formatting_exprs: Vec<_> = log_args
        .formatting_args
        .map(|punctuated| punctuated.into_iter().collect())
        .unwrap_or_default();

    let log::Codegen { patterns, exprs } = match log::Codegen::new(
        &fragments,
        formatting_exprs.len(),
        log_args.format_string.span(),
    ) {
        Ok(val) => val,
        Err(err) => return err.into_compile_error().into(),
    };

    let format_tag =
        construct::interned_string(&format_string, "write", false, None, &parse_quote!(defmt));
    quote!({
        let _typecheck_formatter: defmt::Formatter<'_> = #formatter;
        match (#(&(#formatting_exprs)),*) {
            (#(#patterns),*) => {
                defmt::export::istr(&#format_tag);
                #(#exprs;)*
            }
        }
    })
    .into()
}