py-rs-macros 0.1.1

derive macro for py-rs
Documentation
use proc_macro2::TokenStream;
use quote::quote;
use syn::{Field, FieldsUnnamed, Path, Result};

use crate::{
    attr::{Attr, ContainerAttr, FieldAttr, StructAttr},
    deps::Dependencies,
    DerivedPY,
};

pub(crate) fn tuple(attr: &StructAttr, name: &str, fields: &FieldsUnnamed) -> Result<DerivedPY> {
    let crate_rename = attr.crate_rename();
    let mut formatted_fields = Vec::new();
    let mut dependencies = Dependencies::new(crate_rename.clone());
    for field in &fields.unnamed {
        format_field(
            &crate_rename,
            &mut formatted_fields,
            &mut dependencies,
            field,
        )?;
    }

    Ok(DerivedPY {
        crate_rename,
        inline: quote! {
            format!(
                "tuple[{}]",
                [#(#formatted_fields),*].join(", ")
            )
        },
        enum_def: None,
        inline_flattened: None,
        docs: attr.docs.clone(),
        dependencies,
        export: attr.export,
        export_to: attr.export_to.clone(),
        py_name: name.to_owned(),
        concrete: attr.concrete.clone(),
        bound: attr.bound.clone(),
    })
}

fn format_field(
    crate_rename: &Path,
    formatted_fields: &mut Vec<TokenStream>,
    dependencies: &mut Dependencies,
    field: &Field,
) -> Result<()> {
    let field_attr = FieldAttr::from_attrs(&field.attrs)?;
    field_attr.assert_validity(field)?;

    if field_attr.skip {
        return Ok(());
    }

    let ty = field_attr.type_as(&field.ty);

    formatted_fields.push(match field_attr.type_override {
        Some(ref o) => quote!(#o.to_owned()),
        None if field_attr.inline => quote!(<#ty as #crate_rename::PY>::inline()),
        None => quote!(<#ty as #crate_rename::PY>::name()),
    });

    match (field_attr.inline, field_attr.type_override) {
        (_, Some(_)) => (),
        (false, _) => dependencies.push(&ty),
        (true, _) => dependencies.append_from(&ty),
    };

    Ok(())
}