@@ -35,20 +35,75 @@ pub struct PluggedWalletJSONValues {
3535
3636impl < ' a > JsonDecodable < ' a > for PluggedWalletJSONValues { }
3737
38+
39+ // This struct is used as a helper to free the resource even in case of error.
40+ // It is workaround for Rust's lack of try/catch.
41+ struct ResourceGuard {
42+ storage_handle : i32 ,
43+ item_handle : i32 ,
44+ free_handler : extern fn ( storage_handle : i32 , item_handle : i32 ) -> ErrorCode
45+ }
46+
47+ impl ResourceGuard {
48+ fn new ( storage_handle : i32 ,
49+ item_handle : i32 ,
50+ free_handler : extern fn ( s_handle : i32 , i_handle : i32 ) -> ErrorCode
51+ ) -> Self {
52+ Self {
53+ storage_handle,
54+ item_handle,
55+ free_handler
56+ }
57+ }
58+ }
59+
60+ impl Drop for ResourceGuard {
61+ fn drop ( & mut self ) {
62+ ( self . free_handler ) ( self . storage_handle , self . item_handle ) ;
63+ }
64+ }
65+
66+
3867#[ derive( PartialEq , Debug ) ]
3968struct PluggedStorageIterator {
40- storage : PluggedStorage ,
69+ storage_handle : i32 ,
4170 search_handle : i32 ,
4271 options : SearchOptions ,
72+ fetch_search_next_record_handler : WalletFetchSearchNextRecord ,
73+ get_search_total_count_handler : WalletGetSearchTotalCount ,
74+ get_record_type_handler : WalletGetRecordType ,
75+ get_record_id_handler : WalletGetRecordId ,
76+ get_record_value_handler : WalletGetRecordValue ,
77+ get_record_tags_handler : WalletGetRecordTags ,
78+ free_record_handler : WalletFreeRecord ,
79+ free_search_handler : WalletFreeSearch ,
80+ }
81+
82+ impl PluggedStorageIterator {
83+ fn new ( storage : & PluggedStorage , search_handle : i32 , options : SearchOptions ) -> Self {
84+ Self {
85+ storage_handle : storage. handle ,
86+ search_handle : search_handle,
87+ options : options,
88+ fetch_search_next_record_handler : storage. fetch_search_next_record_handler ,
89+ get_search_total_count_handler : storage. get_search_total_count_handler ,
90+ get_record_type_handler : storage. get_record_type_handler ,
91+ get_record_id_handler : storage. get_record_id_handler ,
92+ get_record_value_handler : storage. get_record_value_handler ,
93+ get_record_tags_handler : storage. get_record_tags_handler ,
94+ free_record_handler : storage. free_record_handler ,
95+ free_search_handler : storage. free_search_handler ,
96+ }
97+ }
4398}
4499
45100impl StorageIterator for PluggedStorageIterator {
46101 fn next ( & mut self ) -> Result < Option < StorageEntity > , WalletStorageError > {
47102 let mut record_handle = -1 ;
48103
49- let err = ( self . storage . fetch_search_next_record_handler ) ( self . storage . handle ,
50- self . search_handle ,
51- & mut record_handle) ;
104+ let err = ( self . fetch_search_next_record_handler ) ( self . storage_handle ,
105+ self . search_handle ,
106+ & mut record_handle) ;
52107
53108 if err == ErrorCode :: WalletItemNotFound {
54109 return Ok ( None ) ;
@@ -57,12 +112,18 @@ impl StorageIterator for PluggedStorageIterator {
57112 return Err ( WalletStorageError :: PluggedStorageError ( err) ) ;
58113 }
59114
115+ let record_free_helper = ResourceGuard {
116+ storage_handle : self . storage_handle ,
117+ item_handle : record_handle,
118+ free_handler : self . free_record_handler
119+ } ;
120+
60121 let type_ = if self . options . retrieve_type . unwrap_or ( false ) {
61122 let mut type_ptr: * const c_char = ptr:: null_mut ( ) ;
62123
63- let err = ( self . storage . get_record_type_handler ) ( self . storage . handle ,
64- record_handle,
65- & mut type_ptr) ;
124+ let err = ( self . get_record_type_handler ) ( self . storage_handle ,
125+ record_handle,
126+ & mut type_ptr) ;
66127
67128 if err != ErrorCode :: Success {
68129 return Err ( WalletStorageError :: PluggedStorageError ( err) ) ;
@@ -74,9 +135,9 @@ impl StorageIterator for PluggedStorageIterator {
74135 let id = {
75136 let mut id_ptr: * const c_char = ptr:: null_mut ( ) ;
76137
77- let err = ( self . storage . get_record_id_handler ) ( self . storage . handle ,
78- record_handle,
79- & mut id_ptr) ;
138+ let err = ( self . get_record_id_handler ) ( self . storage_handle ,
139+ record_handle,
140+ & mut id_ptr) ;
80141
81142 if err != ErrorCode :: Success {
82143 return Err ( WalletStorageError :: PluggedStorageError ( err) ) ;
@@ -87,10 +148,10 @@ impl StorageIterator for PluggedStorageIterator {
87148 let value = if self . options . retrieve_value . unwrap_or ( true ) {
88149 let mut value_bytes: * const u8 = ptr:: null ( ) ;
89150 let mut value_bytes_len: usize = 0 ;
90- let err = ( self . storage . get_record_value_handler ) ( self . storage . handle ,
91- record_handle,
92- & mut value_bytes,
93- & mut value_bytes_len) ;
151+ let err = ( self . get_record_value_handler ) ( self . storage_handle ,
152+ record_handle,
153+ & mut value_bytes,
154+ & mut value_bytes_len) ;
94155
95156 if err != ErrorCode :: Success {
96157 return Err ( WalletStorageError :: PluggedStorageError ( err) ) ;
@@ -102,9 +163,9 @@ impl StorageIterator for PluggedStorageIterator {
102163
103164 let tags = if self . options . retrieve_tags . unwrap_or ( false ) {
104165 let mut tags_ptr: * const c_char = ptr:: null_mut ( ) ;
105- let err = ( self . storage . get_record_tags_handler ) ( self . storage . handle ,
106- record_handle,
107- & mut tags_ptr) ;
166+ let err = ( self . get_record_tags_handler ) ( self . storage_handle ,
167+ record_handle,
168+ & mut tags_ptr) ;
108169
109170 if err != ErrorCode :: Success {
110171 return Err ( WalletStorageError :: PluggedStorageError ( err) ) ;
@@ -114,8 +175,6 @@ impl StorageIterator for PluggedStorageIterator {
114175 Some ( _tags_from_json ( tags_json) ?)
115176 } else { None } ;
116177
117- ( self . storage . free_record_handler ) ( self . storage . handle , record_handle) ;
118-
119178 Ok ( Some ( StorageEntity {
120179 type_ : type_,
121180 name : id,
@@ -128,9 +187,9 @@ impl StorageIterator for PluggedStorageIterator {
128187 let mut total_count = 0 ;
129188
130189 if self . options . retrieve_total_count . unwrap_or ( false ) {
131- let err = ( self . storage . get_search_total_count_handler ) ( self . storage . handle ,
132- self . search_handle ,
133- & mut total_count) ;
190+ let err = ( self . get_search_total_count_handler ) ( self . storage_handle ,
191+ self . search_handle ,
192+ & mut total_count) ;
134193
135194 if err != ErrorCode :: Success {
136195 return Err ( WalletStorageError :: PluggedStorageError ( err) ) ;
@@ -146,11 +205,11 @@ impl StorageIterator for PluggedStorageIterator {
146205
147206impl Drop for PluggedStorageIterator {
148207 fn drop ( & mut self ) {
149- ( self . storage . free_search_handler ) ( self . storage . handle , self . search_handle ) ;
208+ ( self . free_search_handler ) ( self . storage_handle , self . search_handle ) ;
150209 }
151210}
152211
153- #[ derive( PartialEq , Debug , Clone ) ]
212+ #[ derive( PartialEq , Debug ) ]
154213struct PluggedStorage {
155214 handle : i32 ,
156215 add_record_handler : WalletAddRecord ,
@@ -306,6 +365,12 @@ impl WalletStorage for PluggedStorage {
306365 return Err ( WalletStorageError :: PluggedStorageError ( err) ) ;
307366 }
308367
368+ let record_free_helper = ResourceGuard {
369+ storage_handle : self . handle ,
370+ item_handle : record_handle,
371+ free_handler : self . free_record_handler
372+ } ;
373+
309374 let value = if options. retrieve_value {
310375 let mut value_bytes: * const u8 = ptr:: null ( ) ;
311376 let mut value_bytes_len: usize = 0 ;
@@ -343,8 +408,6 @@ impl WalletStorage for PluggedStorage {
343408 tags
344409 } ;
345410
346- let err = ( self . free_record_handler ) ( self . handle , record_handle) ;
347-
348411 if err != ErrorCode :: Success {
349412 return Err ( WalletStorageError :: PluggedStorageError ( err) ) ;
350413 }
@@ -471,12 +534,16 @@ impl WalletStorage for PluggedStorage {
471534 return Err ( WalletStorageError :: PluggedStorageError ( err) ) ;
472535 }
473536
537+ let metadata_free_helper = ResourceGuard {
538+ storage_handle : self . handle ,
539+ item_handle : metadata_handle,
540+ free_handler : self . free_storage_metadata_handler
541+ } ;
542+
474543 let metadata = base64:: decode (
475544 unsafe { CStr :: from_ptr ( metadata_ptr) . to_str ( ) ? }
476545 ) ?;
477546
478- ( self . free_storage_metadata_handler ) ( self . handle , metadata_handle) ;
479-
480547 Ok ( metadata)
481548 }
482549
@@ -502,17 +569,17 @@ impl WalletStorage for PluggedStorage {
502569 }
503570
504571 Ok ( Box :: new (
505- PluggedStorageIterator {
506- storage : self . clone ( ) /* TODO avoid clone. Use Rc or better approach. */ ,
572+ PluggedStorageIterator :: new (
573+ & self ,
507574 search_handle,
508- options : SearchOptions {
575+ SearchOptions {
509576 retrieve_records : Some ( true ) ,
510577 retrieve_total_count : Some ( false ) ,
511578 retrieve_type : Some ( true ) ,
512579 retrieve_value : Some ( true ) ,
513580 retrieve_tags : Some ( true ) ,
514581 }
515- }
582+ )
516583 ) )
517584 }
518585
@@ -533,11 +600,13 @@ impl WalletStorage for PluggedStorage {
533600 return Err ( WalletStorageError :: PluggedStorageError ( err) ) ;
534601 }
535602
536- Ok ( Box :: new ( PluggedStorageIterator {
537- storage : self . clone ( ) /* TODO avoid clone. Use Rc or better approach. */ ,
538- search_handle,
539- options
540- } ) )
603+ Ok ( Box :: new (
604+ PluggedStorageIterator :: new (
605+ & self ,
606+ search_handle,
607+ options
608+ )
609+ ) )
541610 }
542611
543612 fn close ( & mut self ) -> Result < ( ) , WalletStorageError > {
@@ -547,10 +616,22 @@ impl WalletStorage for PluggedStorage {
547616 return Err ( WalletStorageError :: PluggedStorageError ( err) ) ;
548617 }
549618
619+ // invalidate the handle, just in case.
620+ self . handle = -1 ;
621+
550622 Ok ( ( ) )
551623 }
552624}
553625
626+ impl Drop for PluggedStorage {
627+ fn drop ( & mut self ) {
628+ // if storage is not closed, close it before drop.
629+ if self . handle >= 0 {
630+ self . close ( ) ;
631+ }
632+ }
633+ }
634+
554635#[ derive( Debug ) ]
555636pub struct PluggedStorageType {
556637 create_handler : WalletCreate ,
0 commit comments