alloy_sol_macro_expander/expand/
udt.rs
1use 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 #[automatically_derived]
66 impl #name {
67 pub const NAME: &'static str = stringify!(@name);
69
70 #[inline]
72 pub const fn from(value: #underlying_rust) -> Self {
73 Self(value)
74 }
75
76 #[inline]
78 pub const fn into(self) -> #underlying_rust {
79 self.0
80 }
81
82 #[inline]
85 pub fn abi_encode(&self) -> alloy_sol_types::private::Vec<u8> {
86 <Self as alloy_sol_types::SolType>::abi_encode(&self.0)
87 }
88
89 #[inline]
92 pub fn abi_encode_packed(&self) -> alloy_sol_types::private::Vec<u8> {
93 <Self as alloy_sol_types::SolType>::abi_encode_packed(&self.0)
94 }
95 }
96
97 #[automatically_derived]
98 impl alloy_sol_types::SolType for #name {
99 type RustType = #underlying_rust;
100 type Token<'a> = <#underlying_sol as alloy_sol_types::SolType>::Token<'a>;
101
102 const SOL_NAME: &'static str = Self::NAME;
103 const ENCODED_SIZE: Option<usize> = <#underlying_sol as alloy_sol_types::SolType>::ENCODED_SIZE;
104 const PACKED_ENCODED_SIZE: Option<usize> = <#underlying_sol as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE;
105
106 #[inline]
107 fn valid_token(token: &Self::Token<'_>) -> bool {
108 Self::type_check(token).is_ok()
109 }
110
111 #[inline]
112 fn type_check(token: &Self::Token<'_>) -> alloy_sol_types::Result<()> {
113 #type_check_body
114 }
115
116 #[inline]
117 fn detokenize(token: Self::Token<'_>) -> Self::RustType {
118 <#underlying_sol as alloy_sol_types::SolType>::detokenize(token)
119 }
120 }
121
122 #[automatically_derived]
123 impl alloy_sol_types::EventTopic for #name {
124 #[inline]
125 fn topic_preimage_length(rust: &Self::RustType) -> usize {
126 <#underlying_sol as alloy_sol_types::EventTopic>::topic_preimage_length(rust)
127 }
128
129 #[inline]
130 fn encode_topic_preimage(rust: &Self::RustType, out: &mut alloy_sol_types::private::Vec<u8>) {
131 <#underlying_sol as alloy_sol_types::EventTopic>::encode_topic_preimage(rust, out)
132 }
133
134 #[inline]
135 fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken {
136 <#underlying_sol as alloy_sol_types::EventTopic>::encode_topic(rust)
137 }
138 }
139 };
140 };
141 Ok(tokens)
142}