versatiles_derive 0.11.4

A toolbox for converting, checking and serving map tiles in various formats.
Documentation
extern crate proc_macro;
extern crate quote;
extern crate syn;

use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Fields};

#[proc_macro_derive(YamlParser)]
pub fn yaml_parser_derive(input: TokenStream) -> TokenStream {
	let input = parse_macro_input!(input as DeriveInput);
	let name = input.ident;

	let fields = if let Data::Struct(data_struct) = input.data {
		if let Fields::Named(fields_named) = data_struct.fields {
			fields_named.named
		} else {
			panic!("YamlParser can only be derived for structs with named fields");
		}
	} else {
		panic!("YamlParser can only be derived for structs");
	};

	let field_parsing = fields.iter().map(|field| {
		let field_name = &field.ident;
		let field_type = &field.ty;
		let field_str = field_name.as_ref().unwrap().to_string();

		match quote!(#field_type).to_string().as_str() {
			"String" => quote! {
				#field_name: yaml.hash_get_string(#field_str).context(format!("Failed to get '{}'", #field_str))?
			},
			"bool" => quote! {
				#field_name: yaml.hash_get_bool(#field_str).unwrap_or(false)
			},
			"Option < String >" => quote! {
				#field_name: yaml.hash_get_string(#field_str).ok()
			},
			_ => quote! {
				#field_name: yaml.hash_get_str(#field_str).context(format!("Failed to get '{}'", #field_str))?.parse::<#field_type>().context(format!("Failed to parse '{}'", #field_str))?
			},
		}
	});

	let expanded = quote! {
		impl #name {
			pub fn from_yaml(yaml: &YamlWrapper) -> anyhow::Result<Self> {
				Ok(Self {
					#(#field_parsing),*
				})
			}
		}
	};

	TokenStream::from(expanded)
}