ink_codegen/generator/sol/
utils.rs

1// Copyright (C) ink! contributors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use ir::{
16    Callable,
17    InputsIter,
18    IsDocAttribute,
19    Message,
20};
21use proc_macro2::TokenStream as TokenStream2;
22use quote::{
23    quote,
24    quote_spanned,
25};
26use syn::{
27    Attribute,
28    Type,
29    spanned::Spanned,
30};
31
32/// Returns the equivalent Solidity ABI type for the given Rust/ink! type.
33pub fn sol_type(ty: &Type) -> TokenStream2 {
34    quote! {
35        <#ty as ::ink::SolDecode>::SOL_NAME
36    }
37}
38
39/// Returns the equivalent Solidity ABI type for the given Rust/ink! return type.
40///
41/// # Note
42///
43/// Use this function (instead of [`sol_type`]) when return type may be `Result<T, E>`,
44/// because `Result<T, E>` doesn't implement `ink::SolEncode` nor `ink::SolDecode`,
45/// but instead implements `ink::sol::SolResultEncode` and `ink::sol::SolResultDecode`.
46pub fn sol_return_type(ty: &Type) -> TokenStream2 {
47    quote! {
48        <#ty as ::ink::sol::SolResultEncode>::SOL_NAME
49    }
50}
51
52/// Returns Solidity ABI compatible selector of an ink! message.
53pub fn selector(message: &Message) -> TokenStream2 {
54    let name = message
55        .name()
56        .map(ToString::to_string)
57        .unwrap_or_else(|| message.ident().to_string());
58    let signature = call_signature(name, message.inputs());
59    quote! {
60        const {
61            ::ink::codegen::sol::selector_bytes(#signature)
62        }
63    }
64}
65
66/// Returns a `u32` representation of the Solidity ABI compatible selector of an ink!
67/// message.
68pub fn selector_id(message: &Message) -> TokenStream2 {
69    let selector_bytes = selector(message);
70    quote!(
71        {
72            const {
73                ::core::primitive::u32::from_be_bytes(#selector_bytes)
74            }
75        }
76    )
77}
78
79/// Returns the Solidity ABI call signature for the given message name and inputs.
80pub fn call_signature(name: String, inputs: InputsIter) -> TokenStream2 {
81    let mut input_types_len = 0;
82    let sig_param_tys: Vec<_> = inputs
83        .map(|input| {
84            let ty = &*input.ty;
85            let sol_ty = sol_type(ty);
86            let span = input.span();
87            input_types_len += 1;
88
89            quote_spanned!(span=>
90                #sol_ty
91            )
92        })
93        .collect();
94    let sig_arg_fmt_params = (0..input_types_len)
95        .map(|_| "{}")
96        .collect::<Vec<_>>()
97        .join(",");
98    let sig_fmt_lit = format!("{{}}({sig_arg_fmt_params})");
99    quote! {
100        ::ink::codegen::utils::const_format!(#sig_fmt_lit, #name #(,#sig_param_tys)*)
101    }
102}
103
104/// Returns the rustdoc string from the given item attributes.
105pub fn extract_docs(attrs: &[Attribute]) -> String {
106    attrs
107        .iter()
108        .filter_map(|attr| attr.extract_docs())
109        .collect::<Vec<_>>()
110        .join("\n")
111}