sylvia_derive/contract/communication/
querier.rs1use convert_case::Case;
2use proc_macro2::TokenStream;
3use quote::quote;
4use syn::{GenericParam, Generics, Type};
5
6use crate::crate_module;
7use crate::parser::attributes::msg::MsgType;
8use crate::types::associated_types::EmitAssociated;
9use crate::types::msg_field::MsgField;
10use crate::types::msg_variant::{MsgVariant, MsgVariants};
11use crate::utils::SvCasing;
12
13pub struct Querier<'a> {
18 generics: Generics,
19 self_ty: Type,
20 variants: MsgVariants<'a, GenericParam>,
21}
22
23impl<'a> Querier<'a> {
24 pub fn new(generics: Generics, self_ty: Type, variants: MsgVariants<'a, GenericParam>) -> Self {
25 Self {
26 generics,
27 self_ty,
28 variants,
29 }
30 }
31
32 pub fn emit(&self) -> TokenStream {
33 let sylvia = crate_module();
34 let Self {
35 generics,
36 self_ty,
37 variants,
38 ..
39 } = self;
40
41 let where_clause = &generics.where_clause;
42 let generics: Vec<_> = generics.params.iter().collect();
43 let contract = &self_ty;
44
45 let accessor = MsgType::Query.as_accessor_name();
46 let api_path = quote! { < #contract as #sylvia ::types::ContractApi>:: #accessor };
47
48 let querier_methods_impl = variants
49 .variants()
50 .map(|variant| variant.emit_querier_impl(&api_path));
51
52 let querier_methods_declaration = variants
53 .variants()
54 .map(|variant| variant.emit_querier_method_declaration());
55
56 let types_declaration = where_clause
57 .as_ref()
58 .map(EmitAssociated::emit_declaration)
59 .unwrap_or(vec![]);
60
61 let types_implementation = where_clause
62 .as_ref()
63 .map(EmitAssociated::emit_implementation)
64 .unwrap_or(vec![]);
65
66 let bracketed_generics = if !generics.is_empty() {
67 quote! { < #(#generics,)* > }
68 } else {
69 quote! {}
70 };
71
72 quote! {
73 pub trait Querier #bracketed_generics {
74 #(#types_declaration)*
75 #(#querier_methods_declaration)*
76 }
77
78 impl <'sv_querier_lifetime, #(#generics,)* C: #sylvia ::cw_std::CustomQuery> Querier #bracketed_generics for #sylvia ::types::BoundQuerier<'sv_querier_lifetime, C, #contract > #where_clause {
79 #(#types_implementation)*
80 #(#querier_methods_impl)*
81 }
82 }
83 }
84}
85
86trait EmitQuerierMethod {
87 fn emit_querier_impl(&self, api_path: &TokenStream) -> TokenStream;
88 fn emit_querier_method_declaration(&self) -> TokenStream;
89}
90
91impl EmitQuerierMethod for MsgVariant<'_> {
92 fn emit_querier_impl(&self, api_path: &TokenStream) -> TokenStream {
93 let sylvia = crate_module();
94 let name = self.name();
95 let fields = self.fields();
96 let return_type = self.return_type();
97
98 let parameters = fields.iter().map(MsgField::emit_method_field_folded);
99 let fields_names = fields.iter().map(MsgField::name);
100 let variant_name = name.to_case(Case::Snake);
101
102 quote! {
103 fn #variant_name(&self, #(#parameters),*) -> Result< #return_type, #sylvia:: cw_std::StdError> {
104 let query = #api_path :: #variant_name (#(#fields_names),*);
105 self.querier().query_wasm_smart(self.contract(), &query)
106 }
107 }
108 }
109
110 fn emit_querier_method_declaration(&self) -> TokenStream {
111 let sylvia = crate_module();
112 let name = self.name();
113 let return_type = self.return_type();
114
115 let parameters = self
116 .fields()
117 .iter()
118 .map(|field| field.emit_method_field_folded());
119 let variant_name = name.to_case(Case::Snake);
120
121 quote! {
122 fn #variant_name(&self, #(#parameters),*) -> Result< #return_type, #sylvia:: cw_std::StdError>;
123 }
124 }
125}