moverox_codegen/
named_fields.rs1use std::borrow::Cow;
2use std::collections::HashMap;
3
4use quote::quote;
5use unsynn::{Ident, ToTokens as _, TokenStream};
6
7use crate::move_type;
8
9#[derive(Clone)]
11pub(super) struct Rust<'a> {
12 pub(super) attrs: TokenStream,
13 pub(super) ident: Cow<'a, Ident>,
14 pub(super) ty: TokenStream,
15}
16
17pub(super) fn to_rust<'a>(
21 this: &'a move_syn::NamedFields,
22 phantoms: impl Iterator<Item = &'a Ident>,
23 address_map: &HashMap<Ident, TokenStream>,
24 visibility: bool,
25) -> TokenStream {
26 let mut move_fields = to_rust_fields(this, address_map);
27
28 let phantom_data = phantoms.map(|ty| {
29 let field = Ident::new(&format!("_{ty}"), ty.span());
30 quote! {
31 #[serde(skip)]
32 #field: ::std::marker::PhantomData<#ty>
33 }
34 });
35
36 let rs_fields: &mut dyn Iterator<Item = TokenStream> = if let Some(field) = move_fields.next() {
37 &mut std::iter::once(field)
38 .chain(move_fields)
39 .map(|Rust { attrs, ident, ty }| {
40 #[expect(clippy::obfuscated_if_else)]
41 let vis = visibility.then(|| quote!(pub)).unwrap_or_default();
42 quote! {
43 #attrs
44 #vis #ident: #ty
45 }
46 })
47 .chain(phantom_data)
48 } else {
49 &mut std::iter::once(quote! {
50 dummy_field: bool
52 })
53 .chain(phantom_data)
54 };
55
56 quote! {
57 { #(#rs_fields),* }
58 }
59}
60
61pub(super) fn to_rust_fields<'a>(
62 this: &'a move_syn::NamedFields,
63 address_map: &HashMap<Ident, TokenStream>,
64) -> impl Iterator<Item = Rust<'a>> + Clone {
65 this.fields().map(
66 |move_syn::NamedField {
67 attrs, ident, ty, ..
68 }| {
69 Rust {
70 attrs: attrs
71 .iter()
72 .filter(|attr| attr.is_doc())
73 .map(|attr| attr.to_token_stream())
74 .collect(),
75 ident: sanitize_ident(ident),
76 ty: move_type::to_rust_with_substitutions(ty, address_map),
77 }
78 },
79 )
80}
81
82fn sanitize_ident(ident: &Ident) -> Cow<'_, Ident> {
83 let ident_str = ident.to_string();
84 match ident_str.as_str() {
86 "abstract" | "become" | "box" | "do" | "final" | "macro" | "override" | "priv"
87 | "typeof" | "unsized" | "virtual" | "yield" | "try" | "gen" | "as" | "break" | "const"
88 | "continue" | "crate" | "else" | "enum" | "extern" | "false" | "fn" | "for" | "if"
89 | "impl" | "in" | "let" | "loop" | "match" | "mod" | "move" | "mut" | "pub" | "ref"
90 | "return" | "self" | "Self" | "static" | "struct" | "super" | "trait" | "true"
91 | "type" | "unsafe" | "use" | "where" | "while" | "async" | "await" | "dyn" => {
92 Cow::Owned(Ident::new_raw(&ident_str, ident.span()))
93 }
94 _ => Cow::Borrowed(ident),
95 }
96}