alloy_sol_macro_expander/
verbatim.rs1use crate::expand::ExternCrates;
2use proc_macro2::TokenStream;
3use quote::quote;
4use std::collections::BTreeMap;
5
6pub(crate) fn verbatim<T: Verbatim>(t: &T, crates: &ExternCrates) -> TokenStream {
8 let mut s = TokenStream::new();
9 t.to_verbatim_tokens(&mut s, crates);
10 s
11}
12
13pub(crate) trait Verbatim {
15 fn to_verbatim_tokens(&self, s: &mut TokenStream, crates: &ExternCrates);
17}
18
19impl Verbatim for proc_macro2::TokenStream {
20 fn to_verbatim_tokens(&self, s: &mut TokenStream, _crates: &ExternCrates) {
21 s.extend(self.clone());
22 }
23}
24
25pub(crate) struct ToTokensCompat<'a, T: ?Sized + Verbatim>(pub(crate) &'a T, &'a ExternCrates);
28
29impl<T: Verbatim> quote::ToTokens for ToTokensCompat<'_, T> {
30 #[inline]
31 fn to_tokens(&self, tokens: &mut TokenStream) {
32 self.0.to_verbatim_tokens(tokens, self.1)
33 }
34}
35
36impl Verbatim for String {
37 fn to_verbatim_tokens(&self, tokens: &mut TokenStream, crates: &ExternCrates) {
38 let alloy_sol_types = &crates.sol_types;
39 tokens.extend(if self.is_empty() {
40 quote!(#alloy_sol_types::private::String::new())
41 } else {
42 quote!(#alloy_sol_types::private::str_to_owned(#self))
43 })
44 }
45}
46
47impl Verbatim for bool {
48 #[inline]
49 fn to_verbatim_tokens(&self, s: &mut TokenStream, _crates: &ExternCrates) {
50 quote::ToTokens::to_tokens(self, s)
51 }
52}
53
54impl Verbatim for usize {
55 #[inline]
56 fn to_verbatim_tokens(&self, s: &mut TokenStream, _crates: &ExternCrates) {
57 quote::ToTokens::to_tokens(self, s)
58 }
59}
60
61impl<T: Verbatim> Verbatim for Vec<T> {
62 fn to_verbatim_tokens(&self, s: &mut TokenStream, crates: &ExternCrates) {
63 let alloy_sol_types = &crates.sol_types;
64 let iter = self.iter().map(|t| ToTokensCompat(t, crates));
65 s.extend(match self.len() {
66 0 => quote!(#alloy_sol_types::private::Vec::new()),
67 _ => quote!(#alloy_sol_types::private::vec![#(#iter),*]),
68 })
69 }
70}
71
72impl<K: Verbatim, V: Verbatim> Verbatim for BTreeMap<K, V> {
73 fn to_verbatim_tokens(&self, s: &mut TokenStream, crates: &ExternCrates) {
74 let alloy_sol_types = &crates.sol_types;
75 s.extend(if self.is_empty() {
76 quote!(#alloy_sol_types::private::BTreeMap::new())
77 } else {
78 let k = self.keys().map(|t| ToTokensCompat(t, crates));
79 let v = self.values().map(|t| ToTokensCompat(t, crates));
80 quote!(#alloy_sol_types::private::make_btree_map(vec![#( (#k, #v) ),*]))
81 });
82 }
83}
84
85impl<T: Verbatim> Verbatim for Option<T> {
86 fn to_verbatim_tokens(&self, s: &mut TokenStream, crates: &ExternCrates) {
87 let tts = match self {
88 Some(t) => {
89 let mut s = TokenStream::new();
90 t.to_verbatim_tokens(&mut s, crates);
91 quote!(::core::option::Option::Some(#s))
92 }
93 None => quote!(::core::option::Option::None),
94 };
95 s.extend(tts);
96 }
97}
98
99macro_rules! derive_verbatim {
100 () => {};
101
102 (struct $name:ident { $($field:ident),* $(,)? } $($rest:tt)*) => {
103 impl Verbatim for alloy_json_abi::$name {
104 fn to_verbatim_tokens(&self, s: &mut TokenStream, crates: &ExternCrates) {
105 let Self { $($field),* } = self;
106 $(
107 let $field = ToTokensCompat($field, crates);
108 )*
109 let alloy_sol_types = &crates.sol_types;
110 s.extend(quote! {
111 #alloy_sol_types::private::alloy_json_abi::$name {
112 $($field: #$field,)*
113 }
114 });
115 }
116 }
117 derive_verbatim!($($rest)*);
118 };
119
120 (enum $name:ident { $($variant:ident $( { $($field_idx:tt : $field:ident),* $(,)? } )?),* $(,)? } $($rest:tt)*) => {
121 impl Verbatim for alloy_json_abi::$name {
122 fn to_verbatim_tokens(&self, s: &mut TokenStream, crates: &ExternCrates) {
123 match self {$(
124 Self::$variant $( { $($field_idx: $field),* } )? => {
125 $($(
126 let $field = ToTokensCompat($field, crates);
127 )*)?
128 let alloy_sol_types = &crates.sol_types;
129 s.extend(quote! {
130 #alloy_sol_types::private::alloy_json_abi::$name::$variant $( { $($field_idx: #$field),* } )?
131 });
132 }
133 )*}
134 }
135 }
136 derive_verbatim!($($rest)*);
137 };
138}
139
140derive_verbatim! {
141 struct Constructor { inputs, state_mutability }
142 struct Fallback { state_mutability }
143 struct Receive { state_mutability }
144 struct Function { name, inputs, outputs, state_mutability }
145 struct Error { name, inputs }
146 struct Event { name, inputs, anonymous }
147 struct Param { ty, name, components, internal_type }
148 struct EventParam { ty, name, indexed, components, internal_type }
149
150 enum InternalType {
151 AddressPayable { 0: s },
152 Contract { 0: s },
153 Enum { contract: contract, ty: ty },
154 Struct { contract: contract, ty: ty },
155 Other { contract: contract, ty: ty },
156 }
157
158 enum StateMutability {
159 Pure,
160 View,
161 NonPayable,
162 Payable,
163 }
164}