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