moverox_codegen/
positional_fields.rs

1use std::collections::HashMap;
2
3use quote::quote;
4use unsynn::{Ident, ToTokens as _, TokenStream};
5
6use crate::move_type;
7
8/// Transform `(T, U, V)` in Move to the equivalent in Rust.
9///
10/// `bool_if_empty` controls whether a `bool` field is generated if there are no Move fields.
11/// `visibility` controls whether a `pub` visibility modifier is added to the field.
12pub(super) fn to_rust<'a>(
13    this: &move_syn::PositionalFields,
14    phantoms: impl Iterator<Item = &'a Ident>,
15    address_map: &HashMap<Ident, TokenStream>,
16    bool_if_empty: bool,
17    visibility: bool,
18) -> TokenStream {
19    let move_fields = this.fields();
20
21    let phantom_data = phantoms.map(|ty| {
22        quote! {
23            #[serde(skip)]
24            ::std::marker::PhantomData<#ty>
25        }
26    });
27
28    let rs_fields: &mut dyn Iterator<Item = TokenStream> = if this.is_empty() && bool_if_empty {
29        &mut std::iter::once(quote!(bool)).chain(phantom_data)
30    } else {
31        &mut move_fields
32            .map(|d| {
33                let attrs = d.attrs.to_token_stream();
34                let ty = move_type::to_rust_with_substitutions(&d.ty, address_map);
35                #[expect(clippy::obfuscated_if_else)]
36                let vis = visibility.then(|| quote!(pub)).unwrap_or_default();
37                quote! {
38                    #attrs #vis #ty
39                }
40            })
41            .chain(phantom_data)
42    };
43
44    quote! {
45        ( #(#rs_fields),* )
46    }
47}