validated_struct_macros 2.1.0

Macros for validated_struct
Documentation
use super::*;

mod kw {
    syn::custom_keyword!(recursive_accessors);
}

enum FieldAttributes {
    RecurseAccessors,
}
impl Parse for FieldAttributes {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        input.parse::<kw::recursive_accessors>()?;
        Ok(Self::RecurseAccessors)
    }
}

impl Parse for FieldType {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let fork = input.fork();
        match fork.parse::<StructSpec>() {
            Ok(_) => Ok(FieldType::Structure(input.parse()?)),
            Err(_) => Ok(FieldType::Concrete(input.parse()?)),
        }
    }
}
impl Parse for FieldSpec {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let mut attributes = input.call(Attribute::parse_outer)?;
        let mut is_validated_map = false;
        attributes = attributes
            .into_iter()
            .filter(|attr| {
                if attr.path.is_ident("validated") {
                    match attr.parse_args::<FieldAttributes>() {
                        Ok(args) => match args {
                            FieldAttributes::RecurseAccessors => is_validated_map = true,
                        },
                        Err(e) => panic!("{}", e),
                    };
                    false
                } else {
                    true
                }
            })
            .collect();
        let vis = input.parse()?;
        let ident = input.parse()?;
        input.parse::<Token![:]>()?;
        let ty = input.parse()?;
        let constraint = match input.parse::<syn::token::Where>() {
            Ok(_) => {
                let content;
                parenthesized!(content in input);
                Some(content.parse()?)
            }
            Err(_) => None,
        };
        Ok(FieldSpec {
            attributes,
            is_validated_map,
            vis,
            ident,
            ty,
            constraint,
        })
    }
}

#[derive(Default)]
struct Attrs {
    local: Vec<Attribute>,
    recursive: Vec<Attribute>,
}
impl Parse for Attrs {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let mut local = input.call(Attribute::parse_outer)?;
        let split = local
            .iter()
            .position(|a| a.path.is_ident("recursive_attrs"));
        let recursive = if let Some(split) = split {
            local.split_off(split + 1)
        } else {
            Vec::new()
        };
        if split.is_some() {
            local.pop();
        }
        Ok(Attrs { local, recursive })
    }
}
impl Parse for StructSpec {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let visibility: Visibility = input.parse()?;
        let Attrs {
            local: attrs,
            recursive: recursive_attrs,
        } = input.parse()?;
        let ident = input.parse()?;
        let content;
        syn::braced!(content in input);
        Ok(StructSpec {
            visibility,
            attrs,
            recursive_attrs,
            ident,
            fields: content.parse_terminated(FieldSpec::parse)?,
        })
    }
}