1use proc_macro2::*;
2use quote::*;
3use radix_common::prelude::*;
4
5use crate::token_stream_from_str;
6
7pub struct PackageStub {
8 pub blueprints: Vec<BlueprintStub>,
9 pub auxiliary_types: Vec<AuxiliaryType>,
10}
11
12impl ToTokens for PackageStub {
13 fn to_tokens(&self, tokens: &mut TokenStream) {
14 let blueprints = &self.blueprints;
15 let auxiliary_types = &self.auxiliary_types;
16 quote! {
17 #(#blueprints)*
18 #(#auxiliary_types)*
19 }
20 .to_tokens(tokens)
21 }
22}
23
24pub struct BlueprintStub {
27 pub blueprint_name: String,
28 pub fn_signatures: Vec<FnSignature>,
29 pub package_address: PackageAddress,
30}
31
32impl ToTokens for BlueprintStub {
33 fn to_tokens(&self, tokens: &mut TokenStream) {
34 let package_address_bytes = self.package_address.to_vec();
35 let blueprint_name = self.blueprint_name.clone();
36 let owned_blueprint_name = format!("Owned{}", self.blueprint_name);
37 let global_blueprint_name = format!("Global{}", self.blueprint_name);
38
39 let blueprint_name_ident = Ident::new(&self.blueprint_name, Span::call_site());
40 let blueprint_functions_name_ident = Ident::new(
41 format!("{}Functions", &self.blueprint_name).as_str(),
42 Span::call_site(),
43 );
44
45 let functions = self
46 .fn_signatures
47 .iter()
48 .filter(|func| matches!(func.fn_type, FnType::Function))
49 .collect::<Vec<_>>();
50 let methods = self
51 .fn_signatures
52 .iter()
53 .filter(|func| matches!(func.fn_type, FnType::Method { .. }))
54 .collect::<Vec<_>>();
55
56 quote! {
57 extern_blueprint_internal! {
58 PackageAddress::new_or_panic([ #(#package_address_bytes),* ]),
59 #blueprint_name_ident,
60 #blueprint_name,
61 #owned_blueprint_name,
62 #global_blueprint_name,
63 #blueprint_functions_name_ident
64 {
65 #(#functions;)*
66 },
67 {
68 #(#methods;)*
69 }
70 }
71 }
72 .to_tokens(tokens)
73 }
74}
75
76pub struct FnSignature {
77 pub ident: syn::Ident,
78 pub inputs: Vec<(syn::Ident, TokenStream)>,
79 pub output: TokenStream,
80 pub fn_type: FnType,
81}
82
83pub enum FnType {
84 Function,
85 Method { is_mutable_receiver: bool },
86}
87
88impl ToTokens for FnSignature {
89 fn to_tokens(&self, tokens: &mut TokenStream) {
90 let ident = &self.ident;
91 let input_names = &self.inputs.iter().map(|(k, _)| k).collect::<Vec<_>>();
92 let input_types = &self.inputs.iter().map(|(_, v)| v).collect::<Vec<_>>();
93 let output = &self.output;
94
95 let sep = if self.inputs.is_empty() {
96 quote! {}
97 } else {
98 quote! {,}
99 };
100
101 match self.fn_type {
102 FnType::Function => quote! {
103 fn #ident( #( #input_names: #input_types ),* ) -> #output
104 }
105 .to_tokens(tokens),
106 FnType::Method {
107 is_mutable_receiver: true,
108 } => quote! {
109 fn #ident( &mut self #sep #( #input_names: #input_types ),* ) -> #output
110 }
111 .to_tokens(tokens),
112 FnType::Method {
113 is_mutable_receiver: false,
114 } => quote! {
115 fn #ident( &self #sep #( #input_names: #input_types ),* ) -> #output
116 }
117 .to_tokens(tokens),
118 }
119 }
120}
121
122#[derive(Debug, Clone, PartialEq, Eq)]
123pub enum AuxiliaryType {
124 TupleStruct {
125 struct_name: String,
126 field_types: Vec<String>,
127 },
128 NamedFieldsStruct {
129 struct_name: String,
130 fields: IndexMap<String, String>,
131 },
132 Enum {
133 enum_name: String,
134 variants: Vec<EnumVariant>,
135 },
136}
137
138impl ToTokens for AuxiliaryType {
139 fn to_tokens(&self, tokens: &mut TokenStream) {
140 match self {
141 Self::TupleStruct {
142 struct_name,
143 field_types,
144 } => {
145 let struct_name = token_stream_from_str!(struct_name);
146 let field_types = field_types
147 .iter()
148 .map(|string| token_stream_from_str!(string));
149
150 quote! {
151 #[derive(::scrypto::prelude::ScryptoSbor)]
152 pub struct #struct_name(
153 #(
154 #field_types
155 ),*
156 );
157 }
158 .to_tokens(tokens)
159 }
160 Self::NamedFieldsStruct {
161 struct_name,
162 fields,
163 } => {
164 let struct_name = token_stream_from_str!(struct_name);
165 let field_names = fields.keys().map(|string| token_stream_from_str!(string));
166 let field_types = fields.values().map(|string| token_stream_from_str!(string));
167
168 quote! {
169 #[derive(::scrypto::prelude::ScryptoSbor)]
170 pub struct #struct_name {
171 #(
172 #field_names: #field_types
173 ),*
174 }
175 }
176 .to_tokens(tokens)
177 }
178 Self::Enum {
179 enum_name,
180 variants,
181 } => {
182 let enum_name = token_stream_from_str!(enum_name);
183
184 quote! {
185 #[derive(::scrypto::prelude::ScryptoSbor)]
186 pub enum #enum_name {
187 #(
188 #variants
189 ),*
190 }
191 }
192 .to_tokens(tokens)
193 }
194 }
195 }
196}
197
198#[derive(Debug, Clone, PartialEq, Eq)]
199pub enum EnumVariant {
200 Unit {
201 variant_name: String,
202 variant_index: u8,
203 },
204 Tuple {
205 variant_name: String,
206 variant_index: u8,
207 field_types: Vec<String>,
208 },
209 NamedFields {
210 variant_name: String,
211 variant_index: u8,
212 fields: IndexMap<String, String>,
213 },
214}
215
216impl ToTokens for EnumVariant {
217 fn to_tokens(&self, tokens: &mut TokenStream) {
218 match self {
219 Self::Unit {
220 variant_name,
221 variant_index,
222 } => {
223 let variant_name = token_stream_from_str!(variant_name);
224 quote! {
225 #[sbor(discriminator( #variant_index ))]
226 #variant_name
227 }
228 .to_tokens(tokens)
229 }
230 Self::Tuple {
231 variant_name,
232 variant_index,
233 field_types,
234 } => {
235 let variant_name = token_stream_from_str!(variant_name);
236 let field_types = field_types
237 .iter()
238 .map(|string| token_stream_from_str!(string));
239 quote! {
240 #[sbor(discriminator( #variant_index ))]
241 #variant_name (
242 #(
243 #field_types
244 ),*
245 )
246 }
247 .to_tokens(tokens)
248 }
249 Self::NamedFields {
250 variant_name,
251 variant_index,
252 fields,
253 } => {
254 let variant_name = token_stream_from_str!(variant_name);
255 let field_names = fields.keys().map(|string| token_stream_from_str!(string));
256 let field_types = fields.values().map(|string| token_stream_from_str!(string));
257
258 quote! {
259 #[sbor(discriminator( #variant_index ))]
260 #variant_name {
261 #(
262 #field_names: #field_types
263 ),*
264 }
265 }
266 .to_tokens(tokens)
267 }
268 }
269 }
270}