moverox_codegen/move_enum/
mod.rs1use std::collections::HashMap;
2
3use quote::quote;
4use unsynn::{Ident, LiteralString, ToTokens as _, TokenStream};
5
6use crate::generics::GenericsExt;
7use crate::{named_fields, positional_fields};
8
9pub(super) fn to_rust(
11 this: &move_syn::Enum,
12 thecrate: &TokenStream,
13 package: Option<&LiteralString>,
14 module: Option<&Ident>,
15 address_map: &HashMap<Ident, TokenStream>,
16) -> TokenStream {
17 let move_syn::Enum {
18 ident, generics, ..
19 } = this;
20
21 let extra_attrs: TokenStream = package
22 .into_iter()
23 .map(unsynn::ToTokens::to_token_stream)
24 .map(|addr| quote!(#[move_(address = #addr)]))
25 .chain(module.map(|ident| quote!(#[move_(module = #ident)])))
26 .collect();
27
28 let rust_generics = generics
29 .as_ref()
30 .map(GenericsExt::to_rust)
31 .unwrap_or_default();
32
33 let mut phantoms: Option<Vec<_>> = generics.as_ref().and_then(|generics| {
35 generics
36 .phantoms()
37 .next()
38 .is_some()
39 .then(|| generics.phantoms().cloned().collect())
40 });
41 let variants = this
42 .variants()
43 .map(|var| variant_to_rust(var, phantoms.take().as_deref(), address_map));
44
45 let serde_crate = format!("{thecrate}::serde").replace(" ", "");
48 quote! {
49 #[derive(
50 Clone,
51 Debug,
52 PartialEq,
53 Eq,
54 Hash,
55 #thecrate::traits::MoveDatatype,
56 #thecrate::serde::Deserialize,
57 #thecrate::serde::Serialize,
58 )]
59 #[move_(crate = #thecrate::traits)]
60 #[serde(crate = #serde_crate)]
61 #extra_attrs
62 #[allow(non_snake_case)]
63 pub enum #ident #rust_generics {
64 #(#variants),*
65 }
66 }
67}
68
69fn variant_to_rust(
70 this: &move_syn::EnumVariant,
71 phantoms: Option<&[Ident]>,
72 address_map: &HashMap<Ident, TokenStream>,
73) -> TokenStream {
74 use move_syn::FieldsKind as K;
75 let move_syn::EnumVariant {
76 attrs,
77 ident,
78 fields,
79 } = this;
80 let attrs = attrs
81 .iter()
82 .filter(|attr| attr.is_doc())
83 .map(|attr| attr.to_token_stream());
84
85 let bool_if_empty = false;
87 let visibility = false;
89
90 let default_fields = phantoms.map(|phantoms| {
93 positional_fields::to_rust(
94 &Default::default(),
95 phantoms.iter(),
96 address_map,
97 bool_if_empty,
98 visibility,
99 )
100 });
101
102 let fields = fields
103 .as_ref()
104 .map(|kind| match kind {
105 K::Named(named) => named_fields::to_rust(
106 named,
107 phantoms.into_iter().flatten(),
108 address_map,
109 visibility,
110 ),
111 K::Positional(positional) => positional_fields::to_rust(
112 positional,
113 phantoms.into_iter().flatten(),
114 address_map,
115 bool_if_empty,
116 visibility,
117 ),
118 })
119 .or(default_fields)
120 .unwrap_or_default();
121
122 quote! {
123 #(#attrs)*
124 #ident #fields
125 }
126}