1use proc_macro2::TokenStream as TokenStream2;
2use quote::quote;
3use syn::{DataStruct, Ident, ImplGenerics, TypeGenerics, WhereClause, WherePredicate};
4
5pub(crate) use enum_data::encode as encode_enum_data;
6
7use crate::construct;
8
9mod enum_data;
10mod fields;
11
12pub(crate) struct EncodeData {
13 pub(crate) format_tag: TokenStream2,
14 pub(crate) stmts: Vec<TokenStream2>,
15 pub(crate) where_predicates: Vec<WherePredicate>,
16}
17
18pub(crate) fn encode_struct_data(
19 ident: &Ident,
20 data: &DataStruct,
21 defmt_path: &syn::Path,
22) -> syn::Result<EncodeData> {
23 let mut format_string = ident.to_string();
24 let mut stmts = vec![];
25 let mut field_patterns = vec![];
26
27 let (encode_fields_stmts, where_predicates) = fields::codegen(
28 &data.fields,
29 &mut format_string,
30 &mut field_patterns,
31 defmt_path,
32 )?;
33
34 stmts.push(quote!(match self {
35 Self { #(#field_patterns),* } => {
36 #(#encode_fields_stmts;)*
37 }
38 }));
39
40 let format_tag = construct::interned_string(&format_string, "derived", false, None, defmt_path);
41 Ok(EncodeData {
42 format_tag,
43 stmts,
44 where_predicates,
45 })
46}
47
48pub(crate) struct Generics<'a> {
49 pub(crate) impl_generics: ImplGenerics<'a>,
50 pub(crate) type_generics: TypeGenerics<'a>,
51 pub(crate) where_clause: WhereClause,
52}
53
54impl<'a> Generics<'a> {
55 pub(crate) fn codegen(
56 generics: &'a mut syn::Generics,
57 where_predicates: Vec<WherePredicate>,
58 ) -> Self {
59 let mut where_clause: WhereClause = generics.make_where_clause().clone();
60 let (impl_generics: ImplGenerics<'_>, type_generics: TypeGenerics<'_>, _) = generics.split_for_impl();
61
62 // Extend where-clause with `Format` bounds for all field types.
63 where_clause.predicates.extend(iter:where_predicates);
64
65 Self {
66 impl_generics,
67 type_generics,
68 where_clause,
69 }
70 }
71}
72