reifydb_macro_impl/
operator_state.rs1use proc_macro2::TokenStream;
5use quote::{ToTokens, quote};
6use syn::{Data, DeriveInput, Error, Fields, Path, Type, parse_str, parse2};
7
8fn field_types(data: &Data) -> Vec<&Type> {
9 let fields: Vec<&Fields> = match data {
10 Data::Struct(item) => vec![&item.fields],
11 Data::Enum(item) => item.variants.iter().map(|variant| &variant.fields).collect(),
12 Data::Union(item) => return item.fields.named.iter().map(|field| &field.ty).collect(),
13 };
14 let mut seen = Vec::new();
15 let mut types = Vec::new();
16 for field in fields.into_iter().flat_map(|fields| fields.iter()) {
17 let rendered = field.ty.to_token_stream().to_string();
18 if !seen.contains(&rendered) {
19 seen.push(rendered);
20 types.push(&field.ty);
21 }
22 }
23 types
24}
25
26fn field_bounds(data: &Data, trait_path: &str) -> String {
27 field_types(data)
28 .into_iter()
29 .map(|ty| format!("{}: {trait_path}", ty.to_token_stream()))
30 .collect::<Vec<_>>()
31 .join(", ")
32}
33
34pub fn operator_state_impl(attr: TokenStream, item: TokenStream, crate_path: &str) -> TokenStream {
35 if !attr.is_empty() {
36 return Error::new_spanned(attr, "operator_state accepts no argument").to_compile_error();
37 }
38 let input: DeriveInput = match parse2(item.clone()) {
39 Ok(input) => input,
40 Err(err) => return err.to_compile_error(),
41 };
42 let root: Path = match parse_str(crate_path) {
43 Ok(path) => path,
44 Err(err) => return err.to_compile_error(),
45 };
46 let name = &input.ident;
47 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
48 let serde_crate = format!("{crate_path}::row::operator::state::derive::serde");
49 let serialize_bound = field_bounds(&input.data, &format!("{serde_crate}::Serialize"));
50 let deserialize_bound = field_bounds(&input.data, &format!("{serde_crate}::de::DeserializeOwned"));
51 let extra_bounds = quote! {
52 Self: #root::row::operator::state::StateCodec,
53 };
54 let merged_where = match where_clause {
55 Some(existing) => {
56 let predicates = &existing.predicates;
57 quote! { where #predicates, #extra_bounds }
58 }
59 None => quote! { where #extra_bounds },
60 };
61
62 quote! {
63 #[derive(
64 #root::row::operator::state::derive::Serialize,
65 #root::row::operator::state::derive::Deserialize,
66 )]
67 #[serde(crate = #serde_crate)]
68 #[serde(bound(serialize = #serialize_bound, deserialize = #deserialize_bound))]
69 #item
70
71 #[automatically_derived]
72 impl #impl_generics #root::row::operator::state::OperatorState for #name #ty_generics #merged_where {
73 fn encode_state(
74 &self,
75 ) -> ::core::result::Result<#root::row::pod::EncodedPodRow, #root::row::operator::state::StateError> {
76 #root::row::operator::state::encode(self)
77 }
78
79 fn decode_state(
80 bytes: &#root::row::pod::EncodedPodRow,
81 ) -> ::core::result::Result<Self, #root::row::operator::state::StateError> {
82 #root::row::operator::state::decode_body::<Self>(bytes)
83 }
84 }
85 }
86}