df-derive-macros 0.3.0

Procedural derive macro implementation for df-derive.
Documentation
use crate::attrs::{
    FieldConversion, FieldDisposition, LeafOverride, Spanned, parse_field_disposition,
};
use crate::ir::FieldIR;
use crate::lower::binary::parse_as_binary_shape;
use crate::lower::leaf::parse_leaf_spec;
use crate::lower::tuple::{
    FieldAttrRef, reject_attrs_on_tuple, reject_unsupported_wrapped_nested_tuples,
};
use crate::lower::validation::reject_direct_self_reference;
use crate::lower::wrappers::normalize_wrappers;
use crate::type_analysis::{AnalyzedBase, analyze_type};
use syn::Ident;

pub fn lower_field(
    field: &syn::Field,
    name_ident: Ident,
    field_index: Option<usize>,
    struct_name: &Ident,
    generic_params: &[Ident],
) -> Result<Option<FieldIR>, syn::Error> {
    let display_name = name_ident.to_string();
    let disposition = parse_field_disposition(field, &display_name)?;
    if matches!(disposition, FieldDisposition::Skip) {
        return Ok(None);
    }

    let analyzed = analyze_type(&field.ty, generic_params)?;
    reject_direct_self_reference(&analyzed, &display_name, struct_name)?;
    reject_unsupported_wrapped_nested_tuples(&analyzed, &display_name)?;

    let outer_smart_ptr_depth = analyzed.outer_smart_ptr_depth;
    let conversion = match &disposition {
        FieldDisposition::Include(conversion) => conversion,
        FieldDisposition::Skip => unreachable!("skip disposition returned before type analysis"),
    };
    let leaf_override: Option<&Spanned<LeafOverride>> = match conversion {
        FieldConversion::Default | FieldConversion::Binary { .. } => None,
        FieldConversion::LeafOverride(override_) => Some(override_),
    };
    let leaf_override_value = leaf_override.map(|override_| &override_.value);

    let (leaf_spec, wrapper_shape) = match conversion {
        FieldConversion::Binary { span } => {
            if matches!(analyzed.base, AnalyzedBase::Tuple(_)) {
                reject_attrs_on_tuple(
                    field,
                    &display_name,
                    Some(FieldAttrRef::Binary { span: *span }),
                )?;
            }
            let (leaf, trimmed) =
                parse_as_binary_shape(field, &display_name, &analyzed.base, &analyzed.wrappers)?;
            (leaf, normalize_wrappers(&trimmed))
        }
        FieldConversion::Default | FieldConversion::LeafOverride(_) => {
            let leaf_override_span = leaf_override.map(|override_| override_.span);
            let leaf = parse_leaf_spec(
                field,
                &display_name,
                leaf_override_value,
                leaf_override_span,
                analyzed.base,
            )?;
            (leaf, normalize_wrappers(&analyzed.wrappers))
        }
    };

    Ok(Some(FieldIR {
        name: name_ident,
        field_index,
        leaf_spec,
        wrapper_shape,
        outer_smart_ptr_depth,
    }))
}