moverox_codegen/move_struct/
tuple.rs

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