remotia_buffer_utils_macros/
lib.rs1extern crate proc_macro;
2
3use core::panic;
4
5use proc_macro::TokenStream;
6use proc_macro2::{Span, TokenTree};
7use quote::{quote, ToTokens};
8use syn::{parse_macro_input, Ident, ItemStruct};
9
10#[proc_macro_attribute]
11pub fn buffers_map(attr: TokenStream, input: TokenStream) -> TokenStream {
12 let input = parse_macro_input!(input as ItemStruct);
14
15 let field_name = Ident::new(&attr.to_string(), Span::call_site());
17
18 let name = input.ident.clone();
20
21 let field = input
23 .fields
24 .iter()
25 .find(|f| f.ident.as_ref() == Some(&field_name))
26 .unwrap();
27
28 let field_type_tokens = &field
30 .ty
31 .to_token_stream()
32 .into_iter()
33 .collect::<Vec<TokenTree>>();
34
35 let ty = field_type_tokens
36 .get(0)
37 .expect("Unable to read field first token");
38
39 if ty.to_string() != "BuffersMap" {
40 panic!("The field should be of type BuffersMap");
41 }
42
43 let key_type_name = Ident::new(&field_type_tokens
44 .get(2)
45 .expect("Unable to read key type")
46 .to_string(), Span::call_site());
47
48 let expanded = quote! {
50 #input
51
52 impl remotia::traits::PullableFrameProperties<#key_type_name, BytesMut> for #name {
53 fn push(&mut self, key: #key_type_name, value: BytesMut) {
54 self.#field_name.insert(key, value);
55 }
56
57 fn pull(&mut self, key: &#key_type_name) -> Option<BytesMut> {
58 self.#field_name.remove(key)
59 }
60 }
61 };
62
63 TokenStream::from(expanded)
65}