parse segments before to_tokens

This commit is contained in:
Evan Almloff committed 2022-05-25 14:08:31 -05:00
1 parent 71eaafaa00
commit f8143a5fc1
1 file changed
+46 -24
+46 -24
View File
@@ -8,11 +8,42 @@ use ::syn::{
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
pub fn format_args_f_impl(input: IfmtInput) -> Result<TokenStream> { pub fn format_args_f_impl(input: IfmtInput) -> Result<TokenStream> {
let IfmtInput {
format_literal,
positional_args,
named_args,
} = input;
let named_args = named_args.into_iter().map(|(ident, expr)| {
quote! {
#ident = #expr
}
});
Ok(quote! {
format_args!(
#format_literal
#(, #positional_args)*
#(, #named_args)*
)
})
}
#[allow(dead_code)] // dumb compiler does not see the struct being used...
#[derive(Debug)]
pub struct IfmtInput {
pub format_literal: LitStr,
pub positional_args: Vec<Expr>,
pub named_args: Vec<(Ident, Expr)>,
}
impl IfmtInput {
fn parse_segments(self) -> Result<Self> {
let IfmtInput { let IfmtInput {
mut format_literal, mut format_literal,
mut positional_args, mut positional_args,
mut named_args, mut named_args,
} = input; } = self;
let s = format_literal.value(); let s = format_literal.value();
let out_format_literal = &mut String::with_capacity(s.len()); let out_format_literal = &mut String::with_capacity(s.len());
@@ -29,8 +60,7 @@ pub fn format_args_f_impl(input: IfmtInput) -> Result<TokenStream> {
out_format_literal.push('{'); out_format_literal.push('{');
continue; continue;
} }
let (end, colon_or_closing_brace) = let (end, colon_or_closing_brace) = iterator
iterator
.find(|&(_, c)| c == '}' || c == ':') .find(|&(_, c)| c == '}' || c == ':')
.expect(concat!( .expect(concat!(
"Invalid format string literal\n", "Invalid format string literal\n",
@@ -56,6 +86,7 @@ pub fn format_args_f_impl(input: IfmtInput) -> Result<TokenStream> {
continue; continue;
} }
#[derive(Debug)]
enum Segment { enum Segment {
Ident(Ident), Ident(Ident),
LitInt(LitInt), LitInt(LitInt),
@@ -121,32 +152,16 @@ pub fn format_args_f_impl(input: IfmtInput) -> Result<TokenStream> {
} }
} }
} }
let named_args = named_args.into_iter().map(|(ident, expr)| {
quote! {
#ident = #expr
}
});
format_literal = LitStr::new(out_format_literal, format_literal.span()); format_literal = LitStr::new(out_format_literal, format_literal.span());
Ok(quote! { Ok(Self {
format_args!( format_literal,
#format_literal positional_args,
#(, #positional_args)* named_args,
#(, #named_args)*
)
}) })
} }
#[allow(dead_code)] // dumb compiler does not see the struct being used... fn parse_positional_args(input: ParseStream) -> Result<Self> {
pub struct IfmtInput {
pub format_literal: LitStr,
pub positional_args: Vec<Expr>,
pub named_args: Vec<(Ident, Expr)>,
}
impl Parse for IfmtInput {
fn parse(input: ParseStream) -> Result<Self> {
let format_literal = input.parse()?; let format_literal = input.parse()?;
let mut positional_args = vec![]; let mut positional_args = vec![];
loop { loop {
@@ -173,6 +188,7 @@ impl Parse for IfmtInput {
})? })?
.into_iter() .into_iter()
.collect(); .collect();
Ok(Self { Ok(Self {
format_literal, format_literal,
positional_args, positional_args,
@@ -181,6 +197,12 @@ impl Parse for IfmtInput {
} }
} }
impl Parse for IfmtInput {
fn parse(input: ParseStream) -> Result<Self> {
Self::parse_positional_args(input).and_then(|new| new.parse_segments())
}
}
pub fn defer<'a, T: 'a, Drop: 'a>(x: T, drop: Drop) -> impl ::core::ops::DerefMut<Target = T> + 'a pub fn defer<'a, T: 'a, Drop: 'a>(x: T, drop: Drop) -> impl ::core::ops::DerefMut<Target = T> + 'a
where where
Drop: FnOnce(T), Drop: FnOnce(T),