parsable-macro 0.1.1

Macro to generate the `parsable` trait on enums or structs.
Documentation
use quote::quote;
use proc_macro2::TokenStream;
use syn::LitStr;
use crate::utils::make_ident;

pub struct MarkerOutput {
    pub on_parse_start: TokenStream,
    pub on_parse_exit: TokenStream,
    pub on_parse_fail: TokenStream,
}

impl MarkerOutput {
    pub fn from_attributes(declared_markers: &[LitStr], set_markers: &[LitStr], unset_markers: &[LitStr], field_index: Option<usize>) -> Self {
        let mut start = vec![];
        let mut exit = vec![];
        let mut fail = vec![];

        let prefix = match field_index {
            Some(index) => format!("field_{}_", index),
            None => String::new(),
        };

        for marker in declared_markers {
            let marker_str = marker.value().replace("-", "_");
            let var_ident = make_ident(format!("{}{}_id", prefix, marker_str));

            start.push(quote! { let #var_ident = reader__.declare_marker(#marker); });
            exit.insert(0, quote! { reader__.remove_marker(#var_ident); });
        }

        for (marker_list, value) in [set_markers, unset_markers].iter().zip(&[true, false]) {
            for marker in *marker_list {
                let marker_str = marker.value().replace("-", "_");
                let var_ident = make_ident(format!("{}{}_value", prefix, marker_str));

                start.push(quote! { let #var_ident = reader__.set_marker(#marker, #value); });
                fail.insert(0, quote! { reader__.set_marker(#marker, #var_ident); })
            }
        }

        Self {
            on_parse_start: quote! { #(#start)* },
            on_parse_exit: quote! { #(#exit)* },
            on_parse_fail: quote! { #(#fail)* },
        }
    }

    pub fn to_tuple(self) -> (TokenStream, TokenStream, TokenStream) {
        (
            self.on_parse_start,
            self.on_parse_exit,
            self.on_parse_fail,
        )
    }
}