1+ use fallible_iterator:: FallibleIterator ;
2+
13use crate :: { CodesHandle , KeyedMessage , codes_handle:: HandleGenerator , errors:: CodesError } ;
2- use fallible_streaming_iterator:: FallibleStreamingIterator ;
3- use std:: fmt:: Debug ;
4+ use std:: marker:: PhantomData ;
5+
6+ #[ derive( Debug ) ]
7+ pub struct KeyedMessageGenerator < ' a , S : HandleGenerator > {
8+ codes_handle : & ' a mut CodesHandle < S > ,
9+ }
10+
11+ impl < S : HandleGenerator > CodesHandle < S > {
12+ pub fn message_generator < ' a > ( & ' a mut self ) -> KeyedMessageGenerator < ' a , S > {
13+ KeyedMessageGenerator { codes_handle : self }
14+ }
15+ }
416
517/// # Errors
618///
7- /// The `advance()` and ` next()` methods will return [`CodesInternal`](crate::errors::CodesInternal)
19+ /// The `next()` will return [`CodesInternal`](crate::errors::CodesInternal)
820/// when internal ecCodes function returns non-zero code.
9- impl < S : HandleGenerator + Debug > FallibleStreamingIterator for CodesHandle < S > {
10- type Item = KeyedMessage ;
11-
21+ impl < ' ch , S : HandleGenerator > FallibleIterator for KeyedMessageGenerator < ' ch , S > {
22+ type Item = KeyedMessage < ' ch > ;
1223 type Error = CodesError ;
1324
14- fn advance ( & mut self ) -> Result < ( ) , Self :: Error > {
15- // destructor of KeyedMessage calls ecCodes
25+ fn next ( & mut self ) -> Result < Option < Self :: Item > , Self :: Error > {
26+ let new_eccodes_handle = self . codes_handle . source . gen_codes_handle ( ) ? ;
1627
17- let new_eccodes_handle = self . source . gen_codes_handle ( ) ?;
18-
19- self . current_message = if new_eccodes_handle. is_null ( ) {
20- None
28+ if new_eccodes_handle. is_null ( ) {
29+ Ok ( None )
2130 } else {
22- Some ( KeyedMessage {
31+ Ok ( Some ( KeyedMessage {
32+ parent_message : PhantomData ,
2333 message_handle : new_eccodes_handle,
24- } )
25- } ;
26-
27- Ok ( ( ) )
28- }
29-
30- fn get ( & self ) -> Option < & Self :: Item > {
31- self . current_message . as_ref ( )
34+ } ) )
35+ }
3236 }
3337}
3438
3539#[ cfg( test) ]
3640mod tests {
3741 use crate :: {
38- DynamicKeyType ,
42+ DynamicKeyType , FallibleIterator ,
3943 codes_handle:: { CodesHandle , ProductKind } ,
4044 } ;
4145 use anyhow:: { Context , Ok , Result } ;
42- use fallible_streaming_iterator:: FallibleStreamingIterator ;
4346 use std:: path:: Path ;
4447
4548 #[ test]
@@ -48,14 +51,26 @@ mod tests {
4851 let product_kind = ProductKind :: GRIB ;
4952 let mut handle = CodesHandle :: new_from_file ( file_path, product_kind) ?;
5053
51- let msg1 = handle. next ( ) ?. context ( "Message not some" ) ?;
54+ let msg1 = handle
55+ . message_generator ( )
56+ . next ( ) ?
57+ . context ( "Message not some" ) ?;
5258 let key1 = msg1. read_key_dynamic ( "typeOfLevel" ) ?;
59+ drop ( msg1) ;
5360
54- let msg2 = handle. next ( ) ?. context ( "Message not some" ) ?;
61+ let msg2 = handle
62+ . message_generator ( )
63+ . next ( ) ?
64+ . context ( "Message not some" ) ?;
5565 let key2 = msg2. read_key_dynamic ( "typeOfLevel" ) ?;
66+ drop ( msg2) ;
5667
57- let msg3 = handle. next ( ) ?. context ( "Message not some" ) ?;
68+ let msg3 = handle
69+ . message_generator ( )
70+ . next ( ) ?
71+ . context ( "Message not some" ) ?;
5872 let key3 = msg3. read_key_dynamic ( "typeOfLevel" ) ?;
73+ drop ( msg3) ;
5974
6075 assert_eq ! ( key1, DynamicKeyType :: Str ( "isobaricInhPa" . to_string( ) ) ) ;
6176 assert_eq ! ( key2, DynamicKeyType :: Str ( "isobaricInhPa" . to_string( ) ) ) ;
@@ -71,7 +86,7 @@ mod tests {
7186
7287 let mut handle = CodesHandle :: new_from_file ( file_path, product_kind) ?;
7388
74- while let Some ( msg) = handle. next ( ) ? {
89+ while let Some ( msg) = handle. message_generator ( ) . next ( ) ? {
7590 let key = msg. read_key_dynamic ( "shortName" ) ?;
7691
7792 match key {
@@ -91,7 +106,7 @@ mod tests {
91106
92107 let mut handle_collected = vec ! [ ] ;
93108
94- while let Some ( msg) = handle. next ( ) ? {
109+ while let Some ( msg) = handle. message_generator ( ) . next ( ) ? {
95110 handle_collected. push ( msg. try_clone ( ) ?) ;
96111 }
97112
@@ -112,7 +127,7 @@ mod tests {
112127 let product_kind = ProductKind :: GRIB ;
113128
114129 let mut handle = CodesHandle :: new_from_file ( file_path, product_kind) ?;
115- let current_message = handle. next ( ) ?. context ( "Message not some" ) ?;
130+ let current_message = handle. message_generator ( ) . next ( ) ?. context ( "Message not some" ) ?;
116131
117132 assert ! ( !current_message. message_handle. is_null( ) ) ;
118133
@@ -125,17 +140,18 @@ mod tests {
125140 let product_kind = ProductKind :: GRIB ;
126141
127142 let mut handle = CodesHandle :: new_from_file ( file_path, product_kind) ?;
143+ let mut mgen = handle. message_generator ( ) ;
128144
129- assert ! ( handle . next( ) ?. is_some( ) ) ;
130- assert ! ( handle . next( ) ?. is_some( ) ) ;
131- assert ! ( handle . next( ) ?. is_some( ) ) ;
132- assert ! ( handle . next( ) ?. is_some( ) ) ;
133- assert ! ( handle . next( ) ?. is_some( ) ) ;
145+ assert ! ( mgen . next( ) ?. is_some( ) ) ;
146+ assert ! ( mgen . next( ) ?. is_some( ) ) ;
147+ assert ! ( mgen . next( ) ?. is_some( ) ) ;
148+ assert ! ( mgen . next( ) ?. is_some( ) ) ;
149+ assert ! ( mgen . next( ) ?. is_some( ) ) ;
134150
135- assert ! ( handle . next( ) ?. is_none( ) ) ;
136- assert ! ( handle . next( ) ?. is_none( ) ) ;
137- assert ! ( handle . next( ) ?. is_none( ) ) ;
138- assert ! ( handle . next( ) ?. is_none( ) ) ;
151+ assert ! ( mgen . next( ) ?. is_none( ) ) ;
152+ assert ! ( mgen . next( ) ?. is_none( ) ) ;
153+ assert ! ( mgen . next( ) ?. is_none( ) ) ;
154+ assert ! ( mgen . next( ) ?. is_none( ) ) ;
139155
140156 Ok ( ( ) )
141157 }
@@ -151,7 +167,7 @@ mod tests {
151167 // First, filter and collect the messages to get those that we want
152168 let mut level = vec ! [ ] ;
153169
154- while let Some ( msg) = handle. next ( ) ? {
170+ while let Some ( msg) = handle. message_generator ( ) . next ( ) ? {
155171 if msg. read_key_dynamic ( "shortName" ) ? == DynamicKeyType :: Str ( "msl" . to_string ( ) )
156172 && msg. read_key_dynamic ( "typeOfLevel" ) ?
157173 == DynamicKeyType :: Str ( "surface" . to_string ( ) )
0 commit comments