maybe-fatal-derive 0.1.0-beta.4

Code generation for the maybe-fatal crate
Documentation
use syn::{Attribute, meta::ParseNestedMeta};

use crate::attribute::field::LabelMeta;

use super::message::MessageMeta;

#[derive(Clone, Default)]
pub struct MaybeFatal {
    pub message: Option<MessageMeta>,
    pub label: Option<LabelMeta>,
    pub notes: Vec<MessageMeta>,
    pub help_messages: Vec<MessageMeta>,
}

impl MaybeFatal {
    pub fn parse_from_attrs<'a>(
        attrs: impl IntoIterator<Item = &'a Attribute>,
    ) -> syn::Result<Self> {
        let mut this = Self::default();
        for attr in attrs {
            this.try_extend_with(attr)?;
        }

        Ok(this)
    }

    pub fn try_extend_with(&mut self, attr: &Attribute) -> syn::Result<()> {
        if attr.path().is_ident("maybe_fatal") {
            attr.parse_nested_meta(|meta| self.parse_nested_subattribute(meta))
        } else {
            Ok(())
        }
    }

    fn parse_nested_subattribute(&mut self, meta: ParseNestedMeta<'_>) -> syn::Result<()> {
        if meta.path.is_ident("message") {
            self.parse_message(meta)
        } else if meta.path.is_ident("label") {
            self.parse_label(meta)
        } else if meta.path.is_ident("note") {
            self.parse_note(meta)
        } else if meta.path.is_ident("help") {
            self.parse_help(meta)
        } else {
            Err(meta.error("unrecognized meta attribute"))
        }
    }

    fn parse_message(&mut self, meta: ParseNestedMeta<'_>) -> syn::Result<()> {
        if self.message.is_some() {
            return Err(meta.error("repeated `message` meta attribute"));
        }

        let content;
        let _ = syn::parenthesized!(content in meta.input);
        self.message = Some(content.parse()?);

        Ok(())
    }

    fn parse_label(&mut self, meta: ParseNestedMeta<'_>) -> syn::Result<()> {
        if self.label.is_some() {
            return Err(meta.error("repeated `label` meta attribute"));
        }

        self.label = Some(LabelMeta::parse_from_nested_meta(meta)?);

        Ok(())
    }

    fn parse_note(&mut self, meta: ParseNestedMeta<'_>) -> syn::Result<()> {
        let content;
        let _ = syn::parenthesized!(content in meta.input);
        self.notes.push(content.parse()?);

        Ok(())
    }

    fn parse_help(&mut self, meta: ParseNestedMeta<'_>) -> syn::Result<()> {
        let content;
        let _ = syn::parenthesized!(content in meta.input);
        self.help_messages.push(content.parse()?);

        Ok(())
    }
}