kafkaesque_macros/
derive_write.rs1use darling::{ast::Data, FromDeriveInput, FromField};
2use proc_macro::TokenStream;
3use quote::quote;
4use std::iter;
5use syn::{parse, parse_macro_input, DeriveInput, Ident, Variant};
6
7#[derive(FromDeriveInput, Debug)]
8#[darling(supports(struct_named, struct_newtype, struct_unit))]
9struct Params {
10 ident: syn::Ident,
11 data: darling::ast::Data<Variant, StructField>,
12 generics: syn::Generics,
13}
14
15#[derive(Debug, Clone, FromField)]
16struct StructField {
17 ident: Option<Ident>,
18 }
20
21pub fn expand(ts: TokenStream) -> TokenStream {
22 let derive_input = parse_macro_input!(ts as DeriveInput);
23 let params = Params::from_derive_input(&derive_input).expect("Failed to parse inputs");
24
25 let generics = params.generics;
26 let name = params.ident;
27 let fields = match params.data {
28 Data::Struct(fields) => fields,
29 Data::Enum(_) => unimplemented!("Unsupported"),
30 };
31
32 let impl_generics = {
33 let mut g = generics.clone();
34 for type_param in g.type_params_mut() {
35 type_param
36 .bounds
37 .push(parse(quote! { Write }.into()).unwrap());
38 }
39 g
40 };
41
42 let field_names: Vec<proc_macro2::TokenStream> = fields
43 .iter()
44 .map(|field| {
45 field
46 .ident
47 .clone()
48 .map(|ident| quote! {#ident})
49 .unwrap_or(quote! {0})
50 })
51 .collect();
52
53 let size_calculation: Vec<proc_macro2::TokenStream> = field_names
54 .iter()
55 .map(|name| {
56 quote! { Write::calculate_size(&self.#name) }
57 })
58 .chain(iter::once(quote! { 0 }))
59 .collect();
60
61 let writing: Vec<proc_macro2::TokenStream> = field_names
62 .iter()
63 .map(|name| {
64 quote! { Write::write_to(&self.#name, writer).await?;}
65 })
66 .collect();
67
68 let output = quote! {
69 #[automatically_derived]
70 impl #impl_generics crate::formats::codec::Write for #name #generics {
71 fn calculate_size(&self) -> i32 {
72 #(#size_calculation)+*
73 }
74 async fn write_to(&self, writer: &mut (dyn tokio::io::AsyncWrite + Send + Unpin)) -> crate::formats::Result<()> {
75 #(#writing) *
76 Ok(())
77 }
78 }
79 };
80
81 output.into()
82}