asset_derive_macro/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, DeriveInput, Generics, Ident, Result};
4
5mod attr;
6mod error;
7mod ident;
8mod variant;
9
10use attr::Attributes;
11use error::Error;
12use ident::Identifier;
13use variant::Variants;
14
15/// Assets type.
16///
17/// Houses the entire parsed macro contents.
18///
19/// * `name`: Main enum identifier.
20/// * `generics`: Any generic information.
21/// * `attrs`: Base level attributes.
22/// * `variants`: All variants.
23#[derive(Debug)]
24struct Assets<'a> {
25    name: &'a Ident,
26    generics: &'a Generics,
27    attrs: Attributes,
28    variants: Variants,
29}
30
31impl<'a> Assets<'a> {
32    /// Creates an `Assets` type from parsed macro input.
33    ///
34    /// * `input`: Parsed macro input.
35    pub fn from(input: &'a DeriveInput) -> Result<Self> {
36        Ok(Self {
37            name: &input.ident,
38            generics: &input.generics,
39            attrs: Attributes::from(&input.attrs)?,
40            variants: Variants::from(input)?,
41        })
42    }
43
44    /// Builds the entire macro output.
45    pub fn build(self) -> TokenStream {
46        let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
47        let name = self.name;
48        let getters = self.variants.build_getters(&self.attrs);
49        let arms = self.variants.build_arms();
50        quote! {
51            impl #impl_generics #name #ty_generics #where_clause {
52                #(#getters)*
53            }
54
55            impl #impl_generics Asset for #name #ty_generics #where_clause {
56                fn fetch(&self) -> Vec<u8> {
57                    match self {
58                        #(#arms),*
59                    }.to_vec()
60                }
61                fn fetch_static(&self) -> &'static [u8] {
62                    match self {
63                        #(#arms),*
64                    }
65                }
66            }
67        }
68        .into()
69    }
70}
71
72/// Provides a derive macro for the `Asset` trait.
73///
74/// ```ignore
75/// #[derive(Asset)]
76/// ```
77#[proc_macro_derive(Asset, attributes(asset))]
78pub fn derive_asset(input: TokenStream) -> TokenStream {
79    impl_asset(&parse_macro_input!(input as DeriveInput))
80        .unwrap_or_else(|err| err.to_compile_error().into())
81}
82
83/// Lower implementation of `Asset`.
84///
85/// * `input`: Parsed macro input.
86fn impl_asset(input: &DeriveInput) -> Result<TokenStream> {
87    Ok(Assets::from(input)?.build())
88}