66use proc_macro:: TokenStream ;
77use proc_macro2:: { Span , TokenStream as TokenStream2 } ;
88use quote:: { format_ident, quote} ;
9- use syn:: { parse_macro_input, parse_quote, ItemStruct , Type , TypePath } ;
9+ use syn:: { parse_macro_input, parse_quote, ItemStruct , Type } ;
1010
1111#[ derive( Debug , deluxe:: ParseAttributes ) ]
1212#[ deluxe( attributes( view) ) ]
1313struct StructAttrs {
1414 context : Option < syn:: Type > ,
1515}
1616
17- struct ContextAndConstraints < ' a > {
18- context : syn:: Type ,
19- context_constraints : Vec < syn:: WherePredicate > ,
17+ struct Constraints < ' a > {
2018 input_constraints : Vec < & ' a syn:: WherePredicate > ,
2119 impl_generics : syn:: ImplGenerics < ' a > ,
2220 type_generics : syn:: TypeGenerics < ' a > ,
2321}
2422
25- impl < ' a > ContextAndConstraints < ' a > {
23+ impl < ' a > Constraints < ' a > {
2624 fn get ( item : & ' a syn:: ItemStruct ) -> Self {
27- let attrs: StructAttrs = deluxe:: parse_attributes ( item) . unwrap ( ) ;
28-
2925 let ( impl_generics, type_generics, maybe_where_clause) = item. generics . split_for_impl ( ) ;
3026 let input_constraints = maybe_where_clause
3127 . map ( |w| w. predicates . iter ( ) )
3228 . into_iter ( )
3329 . flatten ( )
3430 . collect ( ) ;
3531
36- let ( context, context_constraints) = if let Some ( context) = attrs. context {
37- ( context, vec ! [ ] )
38- } else {
39- let first_type_param = item
40- . generics
41- . type_params ( )
42- . map ( |param| & param. ident )
43- . next ( )
44- . expect ( "no context provided and no type parameters" ) ;
45- let context = Type :: Path ( TypePath {
46- qself : None ,
47- path : first_type_param. clone ( ) . into ( ) ,
48- } ) ;
49-
50- let constraints = vec ! [ parse_quote! {
51- #context: linera_views:: context:: Context + Send + Sync + Clone + ' static
52- } ] ;
53-
54- ( context, constraints)
55- } ;
56-
5732 Self {
58- context,
59- context_constraints,
6033 input_constraints,
6134 impl_generics,
6235 type_generics,
@@ -75,14 +48,25 @@ fn get_extended_entry(e: Type) -> TokenStream2 {
7548}
7649
7750fn generate_view_code ( input : ItemStruct , root : bool ) -> TokenStream2 {
78- let ContextAndConstraints {
79- context,
80- context_constraints,
51+ let Constraints {
8152 input_constraints,
8253 impl_generics,
8354 type_generics,
84- } = ContextAndConstraints :: get ( & input) ;
55+ } = Constraints :: get ( & input) ;
56+
57+ let attrs: StructAttrs = deluxe:: parse_attributes ( & input) . unwrap ( ) ;
58+ let context = attrs. context . unwrap_or_else ( || {
59+ let ident = & input
60+ . generics
61+ . type_params ( )
62+ . next ( )
63+ . expect ( "no `context` given and no type parameters" )
64+ . ident ;
65+ parse_quote ! { #ident }
66+ } ) ;
67+
8568 let struct_name = & input. ident ;
69+ let field_types: Vec < _ > = input. fields . iter ( ) . map ( |field| & field. ty ) . collect ( ) ;
8670
8771 let mut name_quotes = Vec :: new ( ) ;
8872 let mut rollback_quotes = Vec :: new ( ) ;
@@ -93,15 +77,12 @@ fn generate_view_code(input: ItemStruct, root: bool) -> TokenStream2 {
9377 let mut num_init_keys_quotes = Vec :: new ( ) ;
9478 let mut pre_load_keys_quotes = Vec :: new ( ) ;
9579 let mut post_load_keys_quotes = Vec :: new ( ) ;
96- let mut field_constraints = vec ! [ ] ;
9780 for ( idx, e) in input. fields . iter ( ) . enumerate ( ) {
9881 let name = e. ident . clone ( ) . unwrap ( ) ;
99- let ty = & e. ty ;
10082 let test_flush_ident = format_ident ! ( "deleted{}" , idx) ;
10183 let idx_lit = syn:: LitInt :: new ( & idx. to_string ( ) , Span :: call_site ( ) ) ;
10284 let g = get_extended_entry ( e. ty . clone ( ) ) ;
10385 name_quotes. push ( quote ! { #name } ) ;
104- field_constraints. push ( quote ! { #ty: linera_views:: views:: View <#context> } ) ;
10586 rollback_quotes. push ( quote ! { self . #name. rollback( ) ; } ) ;
10687 flush_quotes. push ( quote ! { let #test_flush_ident = self . #name. flush( batch) ?; } ) ;
10788 test_flush_quotes. push ( quote ! { #test_flush_ident } ) ;
@@ -147,14 +128,15 @@ fn generate_view_code(input: ItemStruct, root: bool) -> TokenStream2 {
147128 } ;
148129
149130 quote ! {
150- impl #impl_generics linera_views:: views:: View <#context> for #struct_name #type_generics
131+ impl #impl_generics linera_views:: views:: View for #struct_name #type_generics
151132 where
133+ #context: linera_views:: context:: Context ,
152134 #( #input_constraints, ) *
153- #( #context_constraints, ) *
154- #( #field_constraints, ) *
155- Self : Send + Sync ,
135+ #( #field_types: linera_views:: views:: View <Context = #context>, ) *
156136 {
157- const NUM_INIT_KEYS : usize = #( #num_init_keys_quotes) +* ;
137+ const NUM_INIT_KEYS : usize = #( <#field_types as linera_views:: views:: View >:: NUM_INIT_KEYS ) +* ;
138+
139+ type Context = #context;
158140
159141 fn context( & self ) -> & #context {
160142 use linera_views:: views:: View ;
@@ -211,21 +193,12 @@ fn generate_view_code(input: ItemStruct, root: bool) -> TokenStream2 {
211193}
212194
213195fn generate_root_view_code ( input : ItemStruct ) -> TokenStream2 {
214- let ContextAndConstraints {
215- context,
216- context_constraints,
196+ let Constraints {
217197 input_constraints,
218198 impl_generics,
219199 type_generics,
220- } = ContextAndConstraints :: get ( & input) ;
200+ } = Constraints :: get ( & input) ;
221201 let struct_name = & input. ident ;
222- let mut flushes = Vec :: new ( ) ;
223- let mut deletes = Vec :: new ( ) ;
224- for e in & input. fields {
225- let name = e. ident . clone ( ) . unwrap ( ) ;
226- flushes. push ( quote ! { self . #name. flush( & mut batch) ?; } ) ;
227- deletes. push ( quote ! { self . #name. delete( batch) ; } ) ;
228- }
229202
230203 let increment_counter = if cfg ! ( feature = "metrics" ) {
231204 quote ! {
@@ -241,17 +214,16 @@ fn generate_root_view_code(input: ItemStruct) -> TokenStream2 {
241214 } ;
242215
243216 quote ! {
244- impl #impl_generics linera_views:: views:: RootView <#context> for #struct_name #type_generics
217+ impl #impl_generics linera_views:: views:: RootView for #struct_name #type_generics
245218 where
246219 #( #input_constraints, ) *
247- #( #context_constraints, ) *
248- Self : Send + Sync ,
220+ Self : linera_views:: views:: View + Sync ,
249221 {
250222 async fn save( & mut self ) -> Result <( ) , linera_views:: ViewError > {
251223 use linera_views:: { context:: Context , batch:: Batch , store:: WritableKeyValueStore as _, views:: View } ;
252224 #increment_counter
253225 let mut batch = Batch :: new( ) ;
254- # ( #flushes ) *
226+ self . flush ( & mut batch ) ? ;
255227 if !batch. is_empty( ) {
256228 self . context( ) . store( ) . write_batch( batch) . await ?;
257229 }
@@ -261,28 +233,15 @@ fn generate_root_view_code(input: ItemStruct) -> TokenStream2 {
261233 }
262234}
263235
264- fn hash_view_constraints ( input : & ItemStruct , context : & syn:: Type ) -> Vec < syn:: WherePredicate > {
265- input
266- . fields
267- . iter ( )
268- . map ( |field| {
269- let ty = & field. ty ;
270- parse_quote ! { #ty: linera_views:: views:: HashableView <#context> }
271- } )
272- . collect ( )
273- }
274-
275236fn generate_hash_view_code ( input : ItemStruct ) -> TokenStream2 {
276- let ContextAndConstraints {
277- context,
278- context_constraints,
237+ let Constraints {
279238 input_constraints,
280239 impl_generics,
281240 type_generics,
282- } = ContextAndConstraints :: get ( & input) ;
241+ } = Constraints :: get ( & input) ;
283242 let struct_name = & input. ident ;
284- let hash_constraints = hash_view_constraints ( & input, & context) ;
285243
244+ let field_types = input. fields . iter ( ) . map ( |field| & field. ty ) ;
286245 let mut field_hashes_mut = Vec :: new ( ) ;
287246 let mut field_hashes = Vec :: new ( ) ;
288247 for e in & input. fields {
@@ -292,12 +251,11 @@ fn generate_hash_view_code(input: ItemStruct) -> TokenStream2 {
292251 }
293252
294253 quote ! {
295- impl #impl_generics linera_views:: views:: HashableView <#context> for #struct_name #type_generics
254+ impl #impl_generics linera_views:: views:: HashableView for #struct_name #type_generics
296255 where
256+ #( #field_types: linera_views:: views:: HashableView , ) *
297257 #( #input_constraints, ) *
298- #( #context_constraints, ) *
299- #( #hash_constraints, ) *
300- Self : Send + Sync ,
258+ Self : linera_views:: views:: View + Sync ,
301259 {
302260 type Hasher = linera_views:: sha3:: Sha3_256 ;
303261
@@ -321,24 +279,21 @@ fn generate_hash_view_code(input: ItemStruct) -> TokenStream2 {
321279}
322280
323281fn generate_crypto_hash_code ( input : ItemStruct ) -> TokenStream2 {
324- let ContextAndConstraints {
325- context,
326- context_constraints,
282+ let Constraints {
327283 input_constraints,
328284 impl_generics,
329285 type_generics,
330- } = ContextAndConstraints :: get ( & input) ;
331- let hash_constraints = hash_view_constraints ( & input, & context ) ;
286+ } = Constraints :: get ( & input) ;
287+ let field_types = input. fields . iter ( ) . map ( |field| & field . ty ) ;
332288 let struct_name = & input. ident ;
333289 let hash_type = syn:: Ident :: new ( & format ! ( "{struct_name}Hash" ) , Span :: call_site ( ) ) ;
334290 quote ! {
335- impl #impl_generics linera_views:: views:: CryptoHashView <#context>
291+ impl #impl_generics linera_views:: views:: CryptoHashView
336292 for #struct_name #type_generics
337293 where
294+ #( #field_types: linera_views:: views:: HashableView , ) *
338295 #( #input_constraints, ) *
339- #( #context_constraints, ) *
340- #( #hash_constraints, ) *
341- Self : Send + Sync ,
296+ Self : linera_views:: views:: View + Sync ,
342297 {
343298 async fn crypto_hash( & self ) -> Result <linera_base:: crypto:: CryptoHash , linera_views:: ViewError > {
344299 use linera_base:: crypto:: { BcsHashable , CryptoHash } ;
@@ -376,13 +331,11 @@ fn generate_crypto_hash_code(input: ItemStruct) -> TokenStream2 {
376331}
377332
378333fn generate_clonable_view_code ( input : ItemStruct ) -> TokenStream2 {
379- let ContextAndConstraints {
380- context,
381- context_constraints,
334+ let Constraints {
382335 input_constraints,
383336 impl_generics,
384337 type_generics,
385- } = ContextAndConstraints :: get ( & input) ;
338+ } = Constraints :: get ( & input) ;
386339 let struct_name = & input. ident ;
387340
388341 let mut clone_constraints = vec ! [ ] ;
@@ -391,17 +344,16 @@ fn generate_clonable_view_code(input: ItemStruct) -> TokenStream2 {
391344 for field in & input. fields {
392345 let name = & field. ident ;
393346 let ty = & field. ty ;
394- clone_constraints. push ( quote ! { #ty: ClonableView <#context> } ) ;
347+ clone_constraints. push ( quote ! { #ty: ClonableView } ) ;
395348 clone_fields. push ( quote ! { #name: self . #name. clone_unchecked( ) ? } ) ;
396349 }
397350
398351 quote ! {
399- impl #impl_generics linera_views:: views:: ClonableView <#context> for #struct_name #type_generics
352+ impl #impl_generics linera_views:: views:: ClonableView for #struct_name #type_generics
400353 where
401- #( #context_constraints, ) *
402354 #( #input_constraints, ) *
403355 #( #clone_constraints, ) *
404- Self : Send + Sync ,
356+ Self : linera_views :: views :: View + Sync ,
405357 {
406358 fn clone_unchecked( & mut self ) -> Result <Self , linera_views:: ViewError > {
407359 Ok ( Self {
0 commit comments