moverox_codegen/move_struct/
braced.rs

1use std::collections::HashMap;
2
3use proc_macro2::{Ident, TokenStream};
4use quote::quote;
5
6use crate::named_fields;
7
8pub(super) trait BracedStructExt {
9    /// The contents `{ ... }`, including the braces, for the generated Rust struct.
10    fn to_rust_contents<'a>(
11        &'a self,
12        phantoms: impl Iterator<Item = &'a Ident>,
13        address_map: &HashMap<Ident, TokenStream>,
14    ) -> TokenStream;
15
16    /// The `pub fn new` implementation for the generated Rust struct.
17    fn impl_new<'a>(
18        &'a self,
19        phantoms: impl Iterator<Item = &'a Ident>,
20        address_map: &HashMap<Ident, TokenStream>,
21    ) -> (TokenStream, TokenStream);
22}
23
24impl BracedStructExt for move_syn::BracedStruct {
25    fn to_rust_contents<'a>(
26        &'a self,
27        phantoms: impl Iterator<Item = &'a Ident>,
28        address_map: &HashMap<Ident, TokenStream>,
29    ) -> TokenStream {
30        named_fields::to_rust(
31            &self.fields,
32            phantoms,
33            address_map,
34            true, // visibility
35        )
36    }
37
38    fn impl_new<'a>(
39        &'a self,
40        phantoms: impl Iterator<Item = &'a Ident>,
41        address_map: &HashMap<Ident, TokenStream>,
42    ) -> (TokenStream, TokenStream) {
43        let mut move_fields = named_fields::to_rust_fields(&self.fields, address_map).peekable();
44        let has_fields = move_fields.peek().is_some();
45
46        let args: &mut dyn Iterator<Item = TokenStream> = if has_fields {
47            &mut move_fields
48                .clone()
49                .map(|named_fields::Rust { ident, ty, .. }| quote!(#ident: #ty))
50        } else {
51            &mut std::iter::empty()
52        };
53
54        let assign_args: &mut dyn Iterator<Item = TokenStream> = if !has_fields {
55            &mut std::iter::once(quote!(dummy_field: false))
56        } else {
57            &mut move_fields
58                .clone()
59                .map(|named_fields::Rust { ident, .. }| quote!(#ident))
60        };
61
62        let phantom_data = phantoms.map(|ty| {
63            let field = Ident::new(&format!("_{ty}"), ty.span());
64            quote! {
65                #field: ::std::marker::PhantomData
66            }
67        });
68
69        let args = quote!(#(#args),*);
70        let assignments = quote! {
71            {
72                #(#assign_args,)*
73                #( #phantom_data ),*
74            }
75        };
76        (args, assignments)
77    }
78}