use crate::parse::{Fmt, Section};
use ::devise::proc_macro2::TokenStream as TokenStream2;
use ::devise::quote::quote;
use ::devise::syn;
fn str_match(lit: &syn::LitStr) -> TokenStream2 {
quote! {
if !s.starts_with(#lit) {
return Err(format!("string literal '{}' not matched", #lit));
}
let (_, s) = s.split_at(#lit .as_bytes().len());
}
}
fn capture(field: &syn::Ident) -> TokenStream2 {
quote! {
let #field = match s.parse() {
Ok(v) => v,
Err(e) => return Err(format!("{}", e)),
};
}
}
fn capture_w_lookahead(field: &syn::Ident, lookahead: &syn::LitStr) -> TokenStream2 {
quote! {
let idx = match s.find(#lookahead) {
Some(idx) => idx,
None => return Err(format!("lookahead for '{}' not matched", #lookahead)),
};
let (left, s) = s.split_at(idx);
let (_, s) = s.split_at(#lookahead .as_bytes().len());
let #field = match left.parse() {
Ok(value) => value,
Err(e) => return Err(format!("{}", e)),
};
}
}
pub fn codegen(fmt: Fmt) -> TokenStream2 {
let mut code = vec![];
for s in fmt.sections.iter() {
code.push(match s {
Section::StrMatch(s) => str_match(&s.lit),
Section::CaptureLookahead(s) => capture_w_lookahead(&s.field, &s.lookahead),
Section::Capture(s) => capture(&s.field),
});
}
quote! {
#(#code)*
}
}
pub fn struct_builder(s: &syn::ItemStruct) -> TokenStream2 {
let ident = &s.ident;
let mut fields = vec![];
for field in s.fields.iter() {
let field = field.ident.clone();
fields.push(field.unwrap());
}
quote! {
#ident {
#(#fields),*
}
}
}