alloy_sol_macro_expander/expand/
udt.rs1use super::ExpCtxt;
4use alloy_sol_macro_input::ContainsSolAttrs;
5use ast::ItemUdt;
6use proc_macro2::TokenStream;
7use quote::quote;
8use syn::Result;
9
10pub(super) fn expand(cx: &ExpCtxt<'_>, udt: &ItemUdt) -> Result<TokenStream> {
11 let ItemUdt { name, ty, .. } = udt;
12
13 let (sol_attrs, mut attrs) = udt.split_attrs()?;
14 cx.type_derives(&mut attrs, std::iter::once(ty), true);
15
16 let underlying_sol = cx.expand_type(ty);
17 let underlying_rust = cx.expand_rust_type(ty);
18
19 let type_check_body = if let Some(lit_str) = sol_attrs.type_check {
20 let func_path: syn::Path = lit_str.parse()?;
21 quote! {
22 <#underlying_sol as alloy_sol_types::SolType>::type_check(token)?;
23 #func_path(token)
24 }
25 } else {
26 quote! {
27 <#underlying_sol as alloy_sol_types::SolType>::type_check(token)
28 }
29 };
30
31 let alloy_sol_types = &cx.crates.sol_types;
32
33 let tokens = quote! {
34 #(#attrs)*
35 #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)]
36 #[derive(Clone)]
37 pub struct #name(#underlying_rust);
38
39 const _: () = {
40 use #alloy_sol_types as alloy_sol_types;
41
42 #[automatically_derived]
43 impl alloy_sol_types::private::SolTypeValue<#name> for #underlying_rust {
44 #[inline]
45 fn stv_to_tokens(&self) -> <#underlying_sol as alloy_sol_types::SolType>::Token<'_> {
46 alloy_sol_types::private::SolTypeValue::<#underlying_sol>::stv_to_tokens(self)
47 }
48
49 #[inline]
50 fn stv_eip712_data_word(&self) -> alloy_sol_types::Word {
51 <#underlying_sol as alloy_sol_types::SolType>::tokenize(self).0
52 }
53
54 #[inline]
55 fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec<u8>) {
56 <#underlying_sol as alloy_sol_types::SolType>::abi_encode_packed_to(self, out)
57 }
58
59 #[inline]
60 fn stv_abi_packed_encoded_size(&self) -> usize {
61 <#underlying_sol as alloy_sol_types::SolType>::abi_encoded_size(self)
62 }
63 }
64
65 impl #name {
66 pub const NAME: &'static str = stringify!(#name);
68
69 #[inline]
71 pub const fn from_underlying(value: #underlying_rust) -> Self {
72 Self(value)
73 }
74
75 #[inline]
77 pub const fn into_underlying(self) -> #underlying_rust {
78 self.0
79 }
80
81 #[inline]
84 pub fn abi_encode(&self) -> alloy_sol_types::private::Vec<u8> {
85 <Self as alloy_sol_types::SolType>::abi_encode(&self.0)
86 }
87
88 #[inline]
91 pub fn abi_encode_packed(&self) -> alloy_sol_types::private::Vec<u8> {
92 <Self as alloy_sol_types::SolType>::abi_encode_packed(&self.0)
93 }
94 }
95
96 #[automatically_derived]
97 impl From<#underlying_rust> for #name {
98 fn from(value: #underlying_rust) -> Self {
99 Self::from_underlying(value)
100 }
101 }
102
103 #[automatically_derived]
104 impl From<#name> for #underlying_rust {
105 fn from(value: #name) -> Self {
106 value.into_underlying()
107 }
108 }
109
110 #[automatically_derived]
111 impl alloy_sol_types::SolType for #name {
112 type RustType = #underlying_rust;
113 type Token<'a> = <#underlying_sol as alloy_sol_types::SolType>::Token<'a>;
114
115 const SOL_NAME: &'static str = Self::NAME;
116 const ENCODED_SIZE: Option<usize> = <#underlying_sol as alloy_sol_types::SolType>::ENCODED_SIZE;
117 const PACKED_ENCODED_SIZE: Option<usize> = <#underlying_sol as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE;
118
119 #[inline]
120 fn valid_token(token: &Self::Token<'_>) -> bool {
121 Self::type_check(token).is_ok()
122 }
123
124 #[inline]
125 fn type_check(token: &Self::Token<'_>) -> alloy_sol_types::Result<()> {
126 #type_check_body
127 }
128
129 #[inline]
130 fn detokenize(token: Self::Token<'_>) -> Self::RustType {
131 <#underlying_sol as alloy_sol_types::SolType>::detokenize(token)
132 }
133 }
134
135 #[automatically_derived]
136 impl alloy_sol_types::EventTopic for #name {
137 #[inline]
138 fn topic_preimage_length(rust: &Self::RustType) -> usize {
139 <#underlying_sol as alloy_sol_types::EventTopic>::topic_preimage_length(rust)
140 }
141
142 #[inline]
143 fn encode_topic_preimage(rust: &Self::RustType, out: &mut alloy_sol_types::private::Vec<u8>) {
144 <#underlying_sol as alloy_sol_types::EventTopic>::encode_topic_preimage(rust, out)
145 }
146
147 #[inline]
148 fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken {
149 <#underlying_sol as alloy_sol_types::EventTopic>::encode_topic(rust)
150 }
151 }
152 };
153 };
154 Ok(tokens)
155}