cw_iper_test_macros/
lib.rs1use proc_macro::TokenStream;
2use proc_macro2::TokenTree;
3use quote::quote;
4use syn::{parse_macro_input, DeriveInput, Expr, Lit, Meta};
5
6#[proc_macro_derive(IbcPort, attributes(ibc_port))]
9pub fn derive_ibc_port(input: TokenStream) -> TokenStream {
10 let input = parse_macro_input!(input as DeriveInput);
11
12 let struct_name = &input.ident;
13
14 let port = get_attr("ibc_port", &input.attrs).expect("ibc_port attribute not found");
15
16 let mut f: String = "".to_string();
17
18 if let Meta::NameValue(a) = &port.meta {
19 if let Expr::Lit(b) = &a.value {
20 if let Lit::Str(c) = &b.lit {
21 f = c.value();
22 }
23 }
24 };
25
26 if f == *"" {
27 panic!("port attributes not in corrected format. Requested in format #[port = 'port']")
28 }
29
30 let prepath = prepath();
31
32 let expanded = quote! {
33 impl #struct_name {
34 pub const IBC_PORT: &'static str = #f;
36 }
37 impl #prepath::IbcPortInterface for #struct_name {
38 fn port_name(&self) -> String {
39 #f.to_string()
40 }
41 }
42 };
43
44 TokenStream::from(expanded)
45}
46
47#[proc_macro_derive(Stargate, attributes(stargate))]
51pub fn derive_stargate(input: TokenStream) -> TokenStream {
52 let input = parse_macro_input!(input as DeriveInput);
53 let struct_name = &input.ident;
54
55 let attributes = get_attr("stargate", &input.attrs).expect("stargate attribute not found");
56
57 let mut query = None;
58
59 let mut msgs = None;
60
61 let mut name = None;
62
63 if let Meta::List(list) = &attributes.meta {
64 for (index, token) in list.tokens.clone().into_iter().enumerate() {
65 if let TokenTree::Ident(ident) = token {
66 if ident == "name" {
67 let a: Vec<TokenTree> = list.tokens.clone().into_iter().collect();
68 let a = a[index + 2].clone();
69 name = Some(quote! {#a})
70 }
71 if ident == "query_urls" {
72 let a: Vec<TokenTree> = list.tokens.clone().into_iter().collect();
73 let a = a[index + 2].clone();
74 query = Some(quote! {#a})
75 }
76
77 if ident == "msgs_urls" {
78 let a: Vec<TokenTree> = list.tokens.clone().into_iter().collect();
79 let a = a[index + 2].clone();
80 msgs = Some(quote! {#a})
81 }
82 }
83 }
84 }
85
86 let query = query.expect("query_urls attribute not found");
87 let msgs = msgs.expect("msgs_urls attribute not found");
88
89 let prepath = prepath();
90
91 let expanded = quote! {
92 impl #prepath::StargateUrls for #struct_name {
93
94 fn is_query_type_url(&self, type_url: String) -> bool {
95 <#query as std::str::FromStr>::from_str(&type_url).is_ok()
96 }
97
98 fn is_msg_type_url(&self, type_url: String) -> bool {
99 <#msgs as std::str::FromStr>::from_str(&type_url).is_ok()
100 }
101
102 fn type_urls(&self) -> Vec<String> {
103 let mut urls = Vec::new();
104 urls.extend(<#query as #prepath::strum::IntoEnumIterator>::iter().map(|url| url.to_string()));
105 urls.extend(<#msgs as #prepath::strum::IntoEnumIterator>::iter().map(|url| url.to_string()));
106 urls
107 }
108 }
109
110 impl #prepath::StargateName for #struct_name {
111 fn stargate_name(&self) -> String {
112 #name.to_string()
113 }
114 }
115 };
116
117 TokenStream::from(expanded)
118}
119
120#[proc_macro_attribute]
131pub fn urls(_attr: proc_macro::TokenStream, input: proc_macro::TokenStream) -> TokenStream {
132 let input = parse_macro_input!(input as DeriveInput);
133
134 let prepath = prepath();
135
136 let expanded = quote! {
137 #[derive(
138 #prepath::strum_macros::EnumString,
139 #prepath::strum_macros::EnumIter,
140 #prepath::strum_macros::Display
141 )]
142 #input
143 };
144 TokenStream::from(expanded)
145}
146
147fn get_attr<'a>(attr_ident: &str, attrs: &'a [syn::Attribute]) -> Option<&'a syn::Attribute> {
148 attrs.iter().find(|&attr| {
149 attr.path().segments.len() == 1 && attr.path().segments[0].ident == attr_ident
150 })
151}
152
153#[allow(unreachable_code)]
154fn is_internal() -> bool {
155 #[cfg(feature = "internal")]
156 {
157 return true;
158 }
159 false
160}
161
162fn prepath() -> proc_macro2::TokenStream {
163 if is_internal() {
164 quote! {crate}
165 } else {
166 quote! {cw_iper_test}
167 }
168}