nex_macro/
lib.rs

1#![deny(warnings)]
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{parse_macro_input, DeriveInput, Visibility};
6
7mod decorator;
8mod util;
9
10/// The entry point for the `derive(Packet)` custom derive
11#[proc_macro_derive(Packet, attributes(construct_with, length, length_fn, payload))]
12pub fn derive_packet(input: TokenStream) -> TokenStream {
13    let ast = parse_macro_input!(input as DeriveInput);
14    // ensure struct is public
15    match ast.vis {
16        Visibility::Public(_) => (),
17        _ => {
18            let ts = syn::Error::new(ast.ident.span(), "#[packet] structs must be public")
19                .to_compile_error();
20            return ts.into();
21        }
22    }
23    let name = &ast.ident;
24    let s = match &ast.data {
25        syn::Data::Struct(ref s) => decorator::generate_packet(s, name.to_string()),
26        _ => panic!("Only structs are supported"),
27    };
28    match s {
29        Ok(ts) => ts.into(),
30        Err(e) => e.to_compile_error().into(),
31    }
32}
33
34/// The entry point for the `packet` proc_macro_attribute
35#[proc_macro_attribute]
36pub fn packet(_attrs: TokenStream, code: TokenStream) -> TokenStream {
37    // let _attrs = parse_macro_input!(attrs as AttributeArgs);
38    let input = parse_macro_input!(code as DeriveInput);
39    // enhancement: if input already has Clone and/or Debug, do not add them
40    let s = quote! {
41        #[derive(::nex_macro::Packet, Clone, Debug)]
42        #[allow(unused_attributes)]
43        #input
44    };
45    s.into()
46}