1use syn::{Data, DeriveInput, parse_macro_input};
2
3#[proc_macro_derive(BpfApp, attributes(license, hashmap, array_percpu, ringbuf, prog))]
4pub fn derive_bpf_app(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
5 let DeriveInput { ident, data, .. } = parse_macro_input!(input as DeriveInput);
6
7 struct UserTokens<T> {
8 map_cnt: T,
9 prog_cnt: T,
10 new_field: T,
11 map_step: T,
12 prog_step: T,
13 }
14
15 let ut = UserTokens {
16 map_cnt: quote::quote! {},
17 prog_cnt: quote::quote! {},
18 new_field: quote::quote! {},
19 map_step: quote::quote! {},
20 prog_step: quote::quote! {},
21 };
22
23 let ut = match data {
24 Data::Struct(data) => data.fields.into_iter().fold(ut, |ut, field| {
25 let UserTokens {
26 map_cnt,
27 prog_cnt,
28 new_field,
29 map_step,
30 prog_step,
31 } = ut;
32 let val = field.ident.unwrap();
33 let val_str = format!("{}\0", val);
34 let ty = field.ty;
35 UserTokens {
36 map_cnt: quote::quote! { #map_cnt + <#ty as ebpf_user::kind::AppItem>::MAP },
37 prog_cnt: quote::quote! { #prog_cnt + <#ty as ebpf_user::kind::AppItem>::PROG },
38 new_field: quote::quote! { #new_field #val: <#ty>::named(#val_str), },
39 map_step: quote::quote! {
40 #map_step
41 if let ebpf_user::kind::AppItemKindMut::Map(v) = self.#val.kind_mut() {
42 if counter == index {
43 return Some(v);
44 } else {
45 counter += 1;
46 }
47 }
48 },
49 prog_step: quote::quote! {
50 #prog_step
51 if let ebpf_user::kind::AppItemKindMut::Prog(v) = self.#val.kind_mut() {
52 if counter == index {
53 return Some(v);
54 } else {
55 counter += 1;
56 }
57 }
58 },
59 }
60 }),
61 _ => unimplemented!(),
62 };
63
64 let UserTokens {
65 map_cnt,
66 prog_cnt,
67 new_field,
68 map_step,
69 prog_step,
70 } = ut;
71
72 proc_macro::TokenStream::from(quote::quote! {
73 impl ebpf_user::BpfApp for #ident {
74 const MAP_CNT: usize = 0 #map_cnt;
75 const PROG_CNT: usize = 0 #prog_cnt;
76
77 fn instance() -> Self {
78 use ebpf_user::kind::AppItem;
79
80 #ident {
81 #new_field
82 }
83 }
84
85 fn as_mut_map(&mut self, index: usize) -> Option<&mut ebpf_user::MapRef> {
86 use ebpf_user::kind::AppItem;
87
88 let mut counter = 0;
89 #map_step
90 let _ = counter;
91 None
92 }
93
94 fn as_mut_prog(&mut self, index: usize) -> Option<&mut ebpf_user::ProgRef> {
95 use ebpf_user::kind::AppItem;
96
97 let mut counter = 0;
98 #prog_step
99 let _ = counter;
100 None
101 }
102 }
103 })
104}