11use darling:: { ast:: NestedMeta , Error , FromMeta } ;
2+ use heck:: ToSnakeCase ;
23use proc_macro2:: TokenStream as TokenStream2 ;
34use quote:: { format_ident, quote} ;
45use syn:: Index ;
@@ -24,12 +25,15 @@ struct ContractEventArgs {
2425 crate_path : Path ,
2526 lib : Option < String > ,
2627 data_format : String , // single-value, vec, map
27- prefix_topics : Vec < LitStr > ,
28+ prefix_topics : Option < Vec < LitStr > > ,
2829}
2930
3031impl ContractEventArgs {
3132 pub fn prefix_topics ( & self ) -> impl Iterator < Item = String > + use < ' _ > {
32- self . prefix_topics . iter ( ) . map ( |s| s. value ( ) )
33+ self . prefix_topics
34+ . iter ( )
35+ . flatten ( )
36+ . map ( |s : & LitStr | s. value ( ) )
3337 }
3438}
3539
@@ -110,7 +114,7 @@ fn derive_event_inner<'a>(
110114 } ;
111115
112116 let prefix_topics = match prefix_topics[ ..] {
113- [ ] => vec ! [ ident. to_string( ) ] ,
117+ [ ] => vec ! [ ident. to_string( ) . to_snake_case ( ) ] ,
114118 _ => prefix_topics,
115119 } ;
116120
@@ -193,8 +197,13 @@ fn derive_event_inner<'a>(
193197 topic_params. clone ( ) . map ( |p| ( p. ident , p. type_ ) ) . unzip ( ) ;
194198 let prefix_topic_types = ( 0 ..prefix_topics. len ( ) ) . map ( |_| quote ! { #path:: Symbol } ) ;
195199 let tuple_index_calls = ( 0 ..( prefix_topics. len ( ) + topic_params. count ( ) ) ) . map ( |i| {
196- let i = Index :: from ( i) ;
197- quote ! { self . #i }
200+ if i < prefix_topics. len ( ) {
201+ let i = Index :: from ( i) ;
202+ quote ! { & self . #i }
203+ } else {
204+ let i = Index :: from ( i) ;
205+ quote ! { self . #i }
206+ }
198207 } ) ;
199208 let topic_type = quote ! {
200209 pub struct #topic_type_ident<' a>(
@@ -210,6 +219,8 @@ fn derive_event_inner<'a>(
210219 }
211220 }
212221 impl <' a> #path:: Topics for #topic_type_ident<' a> { }
222+ // TODO: Implement to Vec<Val> for contracttype struct with unnamed fields so that this
223+ // impl is not required here on every type.
213224 impl <' a> #path:: IntoVal <#path:: Env , #path:: Vec <#path:: Val >> for #topic_type_ident<' a> {
214225 fn into_val( & self , env: & #path:: Env ) -> #path:: Vec <#path:: Val > {
215226 ( #( #tuple_index_calls) , * ) . into_val( env)
@@ -219,45 +230,61 @@ fn derive_event_inner<'a>(
219230 // TODO: prefix topics may no be short symbols, handle long symbols too.
220231
221232 // Prepare Data Type.
233+ // TODO: support events with no data.
222234 let data_type_ident = format_ident ! ( "{ident}Data" ) ;
223235 let ( data_type_params_idents, data_type_params_types) : ( Vec < _ > , Vec < _ > ) = params
224236 . iter ( )
225237 . filter ( |p| p. location == ParamLocation :: Data )
226238 . map ( |p| ( p. ident , p. type_ ) )
227239 . unzip ( ) ;
228- let data_type = match data_format {
229- ScSpecEventDataFormat :: SingleValue => quote ! {
230- pub type #data_type_ident<' a> = & ' a #( #data_type_params_types) , * ;
231- impl <' a> #data_type_ident<' a> {
232- pub fn new( #( #data_type_params_idents: & ' a #data_type_params_types) , * ) -> Self {
233- #( #data_type_params_idents) , *
240+ let ( data_type, data_type_call) = match data_format {
241+ ScSpecEventDataFormat :: SingleValue => (
242+ quote ! {
243+ pub type #data_type_ident<' a> = #( #data_type_params_types) * ;
244+ } ,
245+ quote ! {
246+ #( self . #data_type_params_idents) * . clone( )
247+ } ,
248+ ) ,
249+ ScSpecEventDataFormat :: Vec => (
250+ quote ! {
251+ // TODO: Implement optional fields on contracttype.
252+ // TODO: #[#path::contracttype]
253+ pub struct #data_type_ident<' a>(
254+ #( & ' a #data_type_params_types, ) *
255+ ) ;
256+ impl <' a> #data_type_ident<' a> {
257+ pub fn new( #( #data_type_params_idents: & ' a #data_type_params_types) , * ) -> Self {
258+ #data_type_ident( #( #data_type_params_idents) , * )
259+ }
234260 }
235- }
236- } ,
237- ScSpecEventDataFormat :: Vec => quote ! {
238- #[ #path:: contracttype]
239- pub struct #data_type_ident<' a>(
240- #( & ' a #data_type_params_types, ) *
241- ) ;
242- impl <' a> #data_type_ident<' a> {
243- pub fn new( #( #data_type_params_idents: & ' a #data_type_params_types) , * ) -> Self {
244- #data_type_ident( #( #data_type_params_idents) , * )
261+ } ,
262+ quote ! {
263+ #data_type_ident:: <' a>:: new(
264+ #( & self . #data_type_params_idents, ) *
265+ )
266+ } ,
267+ ) ,
268+ ScSpecEventDataFormat :: Map => (
269+ quote ! {
270+ // TODO: #[#path::contracttype]
271+ pub struct #data_type_ident<' a>{
272+ #( #data_type_params_idents: & ' a #data_type_params_types, ) *
245273 }
246- }
247- } ,
248- ScSpecEventDataFormat :: Map => quote ! {
249- #[ #path:: contracttype]
250- pub struct #data_type_ident<' a>{
251- #( #data_type_params_idents: & ' a #data_type_params_types, ) *
252- }
253- impl <' a> #data_type_ident<' a> {
254- pub fn new( #( #data_type_params_idents: & ' a #data_type_params_types) , * ) -> Self {
255- #data_type_ident{
256- #( #data_type_params_idents, ) *
274+ impl <' a> #data_type_ident<' a> {
275+ pub fn new( #( #data_type_params_idents: & ' a #data_type_params_types) , * ) -> Self {
276+ #data_type_ident{
277+ #( #data_type_params_idents, ) *
278+ }
257279 }
258280 }
259- }
260- } ,
281+ } ,
282+ quote ! {
283+ #data_type_ident:: <' a>:: new(
284+ #( & self . #data_type_params_idents, ) *
285+ )
286+ } ,
287+ ) ,
261288 } ;
262289
263290 // Output.
@@ -275,9 +302,7 @@ fn derive_event_inner<'a>(
275302 )
276303 }
277304 fn data( & ' a self ) -> Self :: Data {
278- #data_type_ident:: <' a>:: new(
279- #( & self . #data_type_params_idents, ) *
280- )
305+ #data_type_call
281306 }
282307 }
283308 } ;
0 commit comments