Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Extractors

Extractors are types implementing FromInput that pull structured data from a proc macro Input. Mark element params with #[zyn(input)] to auto-resolve them — they won’t be passed at the call site.

#[zyn::element]
fn my_element(
    #[zyn(input)] item: syn::DeriveInput,
    #[zyn(input)] fields: zyn::Fields,
    label: syn::Ident,                       // prop — passed at @call site
) -> zyn::TokenStream {
    zyn::zyn! { /* ... */ }
}

All wrapper extractors implement Deref/DerefMut to their inner type and provide an inner(self) -> T method.

Extractor Types

TypeExtractsUse Case
Attr<T>T::from_input(input)#[derive(Attribute)] structs
Extract<T>T::from_input(input)General FromInput wrapper
Fields<T>Struct fieldsDefaults to syn::Fields
VariantsEnum variantsVec<syn::Variant>
Data<T>Derive dataDefaults to syn::Data

Attr<T>

For attribute structs created with #[derive(Attribute)]:

#[zyn::element]
fn my_element(
    #[zyn(input)] cfg: zyn::Attr<MyConfig>,
    name: syn::Ident,
) -> zyn::TokenStream {
    if cfg.skip { return zyn::TokenStream::new(); }
    zyn::zyn! { /* ... */ }
}

Extract<T>

General-purpose wrapper for any FromInput type:

#[zyn::element]
fn my_element(
    #[zyn(input)] generics: zyn::Extract<syn::Generics>,
) -> zyn::TokenStream {
    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
    zyn::zyn! { /* ... */ }
}

Fields<T>

Extracts syn::Fields from a struct input. Generic over T: FromFields:

TBehaviour
syn::Fields (default)Returns any field shape
syn::FieldsNamedErrors if not named fields
syn::FieldsUnnamedErrors if not unnamed fields
#[zyn::element]
fn struct_element(
    #[zyn(input)] fields: zyn::Fields,
) -> zyn::TokenStream {
    zyn::zyn!(const COUNT: usize = {{ fields.len() }};)
}

With a specific field kind:

#[zyn::element]
fn named_struct_element(
    #[zyn(input)] fields: zyn::Fields<syn::FieldsNamed>,
) -> zyn::TokenStream {
    let names: Vec<_> = fields.named.iter().map(|f| &f.ident).collect();
    zyn::zyn! { /* ... */ }
}

Can also be used outside elements:

let fields = zyn::Fields::from_input(&input)?;

Variants

Extracts Vec<syn::Variant> from an enum input. Errors if not an enum:

#[zyn::element]
fn variant_names(
    #[zyn(input)] variants: zyn::Variants,
) -> zyn::TokenStream {
    zyn::zyn! {
        @for (v in variants.iter()) {
            const {{ v.ident | screaming }}: &str = {{ v.ident | str }};
        }
    }
}

Data<T>

Extracts syn::Data from a derive input. Generic over T: FromData. Only works with derive inputs:

TBehaviour
syn::Data (default)Returns any data kind
syn::DataStructErrors if not a struct
syn::DataEnumErrors if not an enum
syn::DataUnionErrors if not a union
#[zyn::element]
fn struct_data_element(
    #[zyn(input)] data: zyn::Data<syn::DataStruct>,
) -> zyn::TokenStream {
    zyn::zyn!(const FIELD_COUNT: usize = {{ data.fields.len() }};)
}

Syn Types as Extractors

FromInput is implemented for syn types directly — use them as #[zyn(input)] params:

Derive Input Types

TypeMatches
syn::DeriveInputAny derive input
syn::DataStructStruct data only
syn::DataEnumEnum data only
syn::DataUnionUnion data only

Item Input Types

TypeMatches
syn::ItemAny item
syn::ItemFnfn
syn::ItemStructstruct
syn::ItemEnumenum
syn::ItemUnionunion
syn::ItemTraittrait
syn::ItemImplimpl
syn::ItemTypetype
syn::ItemModmod
syn::ItemConstconst
syn::ItemStaticstatic
syn::ItemUseuse
syn::ItemExternCrateextern crate
syn::ItemForeignModextern "C"

Cross-Input Extraction

syn::ItemStruct, syn::ItemEnum, and syn::ItemUnion also work with derive inputs — zyn reconstructs the item type from the derive data:

#[zyn::element]
fn struct_element(
    #[zyn(input)] s: syn::ItemStruct,
) -> zyn::TokenStream {
    // Works whether input is Input::Item or Input::Derive
    zyn::zyn! { /* ... */ }
}

All other item types require an Input::Item context.