hitbox-derive 0.2.1

Derive macros for hitbox caching framework
Documentation
use darling::{FromDeriveInput, FromField, ast::Data, util::Ignored};
use syn::{Error, Ident};

#[derive(Debug, FromField)]
#[darling(attributes(key_extract))]
pub(crate) struct FieldAttributes {
    pub(crate) ident: Option<Ident>,
    #[darling(default)]
    pub(crate) skip: bool,
    #[darling(default)]
    pub(crate) name: Option<String>,
}

#[derive(Debug)]
pub(crate) struct Field<'a> {
    pub(crate) attributes: &'a FieldAttributes,
    pub(crate) index: usize,
}

impl<'a> Field<'a> {
    pub(crate) fn new(_source: &'a Source, attributes: &'a FieldAttributes, index: usize) -> Self {
        Self { attributes, index }
    }

    pub(crate) fn key_name(&self) -> String {
        self.attributes
            .name
            .clone()
            .or_else(|| self.attributes.ident.as_ref().map(|i| i.to_string()))
            .unwrap_or_else(|| self.index.to_string())
    }

    pub(crate) fn is_skipped(&self) -> bool {
        self.attributes.skip
    }
}

#[derive(Debug, FromDeriveInput)]
#[darling(attributes(key_extract), supports(struct_any))]
pub(crate) struct Source {
    pub(crate) ident: Ident,
    pub(crate) data: Data<Ignored, FieldAttributes>,
}

impl Source {
    pub(crate) fn struct_fields(&self) -> Result<impl Iterator<Item = Field<'_>>, Error> {
        match &self.data {
            Data::Struct(fields) => Ok(fields
                .iter()
                .enumerate()
                .map(|(index, attributes)| Field::new(self, attributes, index))),
            _ => Err(Error::new(
                self.ident.span(),
                "KeyExtract can only be derived for structs",
            )),
        }
    }
}