sylvia_derive/interface/communication/
api.rs

1use crate::crate_module;
2use crate::parser::variant_descs::AsVariantDescs;
3use crate::parser::{Custom, MsgType};
4use crate::types::associated_types::{AssociatedTypes, ItemType};
5use crate::types::msg_variant::MsgVariants;
6use proc_macro2::TokenStream;
7use quote::quote;
8use syn::ItemTrait;
9
10/// Emits `InterfaceMessagesApi` trait.
11///
12/// The `InterfaceMessagesApi` is a helper trait to access messages generated by the `interface`
13/// macro.
14/// It ease the dispatch of generic types.
15pub struct Api<'a> {
16    source: &'a ItemTrait,
17    custom: &'a Custom,
18    associated_types: &'a AssociatedTypes<'a>,
19}
20
21impl<'a> Api<'a> {
22    pub fn new(
23        source: &'a ItemTrait,
24        custom: &'a Custom,
25        associated_types: &'a AssociatedTypes<'a>,
26    ) -> Self {
27        Self {
28            source,
29            custom,
30            associated_types,
31        }
32    }
33
34    pub fn emit(&self) -> TokenStream {
35        let sylvia = crate_module();
36        let Self {
37            source,
38            custom,
39            associated_types,
40        } = self;
41
42        let where_clause = &self.associated_types.as_where_clause();
43        let custom_query = custom.query_or_default();
44        let interface_name = &source.ident;
45        let generics: Vec<_> = associated_types
46            .without_error()
47            .map(ItemType::as_name)
48            .collect();
49        let exec_variants = MsgVariants::new(
50            source.as_variants(),
51            MsgType::Exec,
52            &generics,
53            &source.generics.where_clause,
54        );
55        let query_variants = MsgVariants::new(
56            source.as_variants(),
57            MsgType::Query,
58            &generics,
59            &source.generics.where_clause,
60        );
61        let sudo_variants = MsgVariants::new(
62            source.as_variants(),
63            MsgType::Sudo,
64            &generics,
65            &source.generics.where_clause,
66        );
67
68        let exec_generics = &exec_variants.used_generics();
69        let query_generics = &query_variants.used_generics();
70        let sudo_generics = &sudo_variants.used_generics();
71
72        let phantom = if !generics.is_empty() {
73            quote! {
74                _phantom: std::marker::PhantomData<( #(#generics,)* )>,
75            }
76        } else {
77            quote! {}
78        };
79
80        quote! {
81            pub trait InterfaceMessagesApi {
82                type Exec;
83                type Query;
84                type Sudo;
85                type Querier<'querier>;
86            }
87
88            impl<Contract: #interface_name> InterfaceMessagesApi for Contract {
89                type Exec = ExecMsg < #(<Contract as #interface_name >:: #exec_generics,)* >;
90                type Query = QueryMsg < #(<Contract as #interface_name >:: #query_generics,)* >;
91                type Sudo = SudoMsg < #(<Contract as #interface_name >:: #sudo_generics ,)* >;
92                type Querier<'querier> = #sylvia ::types::BoundQuerier<'querier, #custom_query, Contract >;
93            }
94
95            impl<'sv_iface_msg_api, Error, #(#generics),*> InterfaceMessagesApi for dyn #interface_name < Error = Error, #(#generics = #generics,)* > + 'sv_iface_msg_api {
96                type Exec = ExecMsg < #(#exec_generics,)* >;
97                type Query = QueryMsg < #(#query_generics,)* >;
98                type Sudo = SudoMsg < #(#sudo_generics,)* >;
99                type Querier<'querier> = #sylvia ::types::BoundQuerier<'querier, #custom_query, Self >;
100            }
101
102            pub struct Api < #(#generics,)* > {
103                #phantom
104            }
105
106            #[allow(deprecated)]
107            impl < #(#generics,)* > #sylvia ::types::InterfaceApi for Api < #(#generics,)* > #where_clause {
108                type Exec = ExecMsg < #(#exec_generics,)* >;
109                type Query = QueryMsg < #(#query_generics,)* >;
110                type Sudo = SudoMsg < #(#sudo_generics,)* >;
111                type Querier<'querier, Contract> = #sylvia ::types::BoundQuerier<'querier, #custom_query, Contract >;
112            }
113        }
114    }
115}