sark-gen 0.28.1

Sark proc-macro generators
Documentation
use plan::encoding;

use crate::{
    json::{field, mode, plan, plan::Scope},
    runtime::paths::Paths,
};

pub(in crate::json) fn expand(
    paths: &Paths,
    name: &syn::Ident,
    vis: &syn::Visibility,
    generics: &syn::Generics,
    fields: &[plan::JsonField],
    mode: &mode::Mode,
    marker: &syn::Ident,
) -> syn::Result<proc_macro2::TokenStream> {
    let ns_json = &paths.json;
    let scoped = quote::format_ident!("{}Scoped", name);
    let mapped = fields
        .iter()
        .map(|source| {
            Ok(plan::JsonField {
                ident: source.ident.clone(),
                bind: source.bind.clone(),
                ty: source
                    .mode
                    .task_type(paths, &source.ty, &syn::parse_quote!('d))?,
                vis: source.vis.clone(),
                name: source.name.clone(),
                mode: source.mode,
            })
        })
        .collect::<syn::Result<Vec<_>>>()?;
    let shape = plan::Plan {
        mode,
        fields: mapped,
    };
    let decls = shape
        .fields
        .iter()
        .map(|field| {
            let ident = &field.ident;
            let ty = field::proof_type(paths, &field.ty, field.mode)?;
            let vis = &field.vis;
            Ok(quote::quote!(#vis #ident: #ty))
        })
        .collect::<syn::Result<Vec<_>>>()?;
    let mut req_gens = generics.clone();
    req_gens.params.insert(0, syn::parse_quote!('d));
    let (req_impl, req_ty, req_pred) = req_gens.split_for_impl();
    let (own_impl, owned_ty, own_pred) = generics.split_for_impl();
    let names = encoding::Names::new(&req_gens);
    let plan::Emission { lengths, writes } = shape.encoding(paths, Scope::Object, &names)?;
    let encode = encoding::emit(
        paths,
        &req_gens,
        quote::quote!(#scoped #req_ty),
        &names,
        &lengths,
        &writes,
    );

    Ok(quote::quote! {
        #[doc(hidden)]
        #vis struct #scoped #req_impl #req_pred {
            #(#decls,)*
            #[doc(hidden)]
            pub #marker: ::core::marker::PhantomData<&'d ()>,
        }

        impl #own_impl #ns_json::segment::IntoRequest for #name #owned_ty #own_pred {
            type Request<'d> = #scoped #req_ty;
        }

        #encode
    })
}