sga-macros 0.1.0

Macros for the sga crate.
Documentation
extern crate proc_macro;

use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::{parse::{Parse, ParseStream}, parse_macro_input, Expr, Ident, Token, Type};

struct ReadFieldInput {
    reader: Expr,
    _comma1: Token![,],
    enum_name: Ident,
    _colon2: Token![::],
    variant: Ident,
    _comma2: Token![,],
    output_type: Type,
}

impl Parse for ReadFieldInput {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        Ok(ReadFieldInput {
            reader: input.parse()?,
            _comma1: input.parse()?,
            enum_name: input.parse()?,
            _colon2: input.parse()?,
            variant: input.parse()?,
            _comma2: input.parse()?,
            output_type: input.parse()?,
        })
    }
}

#[proc_macro]
pub fn read_field(input: TokenStream) -> TokenStream {
    let ReadFieldInput {
        reader,
        enum_name,
        variant,
        output_type,
        ..
    } = parse_macro_input!(input as ReadFieldInput);

    let output_type = quote!(#output_type).to_string();

    let method = format_ident!("read_{}", output_type);

    let generated = if output_type == "u8" {
        quote! {{
            use byteorder::{LittleEndian, BigEndian, ReadBytesExt};
    
            #reader.#method().map_err(|_| {
                #enum_name::#variant("Failed to parse version number".to_string())
            })
        }}
    } else {
        quote! {{
            use byteorder::{LittleEndian, BigEndian, ReadBytesExt};
    
            #reader.#method::<LittleEndian>().map_err(|_| {
                #enum_name::#variant("Failed to parse version number".to_string())
            })
        }}
    };

    generated.into()
}