@@ -25,6 +25,15 @@ pub struct ImapStream<R: Read + Write> {
25
25
decode_needs : usize ,
26
26
/// The buffer.
27
27
buffer : Buffer ,
28
+
29
+ /// True if the stream should not return any more items.
30
+ ///
31
+ /// This is set when reading from a stream
32
+ /// returns an error.
33
+ /// Afterwards the stream returns only `None`
34
+ /// and `poll_next()` does not read
35
+ /// from the underlying stream.
36
+ read_closed : bool ,
28
37
}
29
38
30
39
impl < R : Read + Write + Unpin > ImapStream < R > {
@@ -34,6 +43,7 @@ impl<R: Read + Write + Unpin> ImapStream<R> {
34
43
inner,
35
44
buffer : Buffer :: new ( ) ,
36
45
decode_needs : 0 ,
46
+ read_closed : false ,
37
47
}
38
48
}
39
49
@@ -132,6 +142,52 @@ impl<R: Read + Write + Unpin> ImapStream<R> {
132
142
}
133
143
}
134
144
}
145
+
146
+ fn do_poll_next (
147
+ mut self : Pin < & mut Self > ,
148
+ cx : & mut Context < ' _ > ,
149
+ ) -> Poll < Option < io:: Result < ResponseData > > > {
150
+ let this = & mut * self ;
151
+ if let Some ( response) = this. decode ( ) ? {
152
+ return Poll :: Ready ( Some ( Ok ( response) ) ) ;
153
+ }
154
+ loop {
155
+ this. buffer . ensure_capacity ( this. decode_needs ) ?;
156
+ let buf = this. buffer . free_as_mut_slice ( ) ;
157
+
158
+ // The buffer should have at least one byte free
159
+ // before we try reading into it
160
+ // so we can treat 0 bytes read as EOF.
161
+ // This is guaranteed by `ensure_capacity()` above
162
+ // even if it is called with 0 as an argument.
163
+ debug_assert ! ( !buf. is_empty( ) ) ;
164
+
165
+ #[ cfg( feature = "runtime-async-std" ) ]
166
+ let num_bytes_read = ready ! ( Pin :: new( & mut this. inner) . poll_read( cx, buf) ) ?;
167
+
168
+ #[ cfg( feature = "runtime-tokio" ) ]
169
+ let num_bytes_read = {
170
+ let buf = & mut tokio:: io:: ReadBuf :: new ( buf) ;
171
+ let start = buf. filled ( ) . len ( ) ;
172
+ ready ! ( Pin :: new( & mut this. inner) . poll_read( cx, buf) ) ?;
173
+ buf. filled ( ) . len ( ) - start
174
+ } ;
175
+
176
+ if num_bytes_read == 0 {
177
+ if this. buffer . used ( ) > 0 {
178
+ return Poll :: Ready ( Some ( Err ( io:: Error :: new (
179
+ io:: ErrorKind :: UnexpectedEof ,
180
+ "bytes remaining in stream" ,
181
+ ) ) ) ) ;
182
+ }
183
+ return Poll :: Ready ( None ) ;
184
+ }
185
+ this. buffer . extend_used ( num_bytes_read) ;
186
+ if let Some ( response) = this. decode ( ) ? {
187
+ return Poll :: Ready ( Some ( Ok ( response) ) ) ;
188
+ }
189
+ }
190
+ }
135
191
}
136
192
137
193
/// Abstraction around needed buffer management.
@@ -273,46 +329,18 @@ impl<R: Read + Write + Unpin> Stream for ImapStream<R> {
273
329
type Item = io:: Result < ResponseData > ;
274
330
275
331
fn poll_next ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Option < Self :: Item > > {
276
- let this = & mut * self ;
277
- if let Some ( response) = this. decode ( ) ? {
278
- return Poll :: Ready ( Some ( Ok ( response) ) ) ;
332
+ if self . read_closed {
333
+ return Poll :: Ready ( None ) ;
279
334
}
280
- loop {
281
- this. buffer . ensure_capacity ( this. decode_needs ) ?;
282
- let buf = this. buffer . free_as_mut_slice ( ) ;
283
-
284
- // The buffer should have at least one byte free
285
- // before we try reading into it
286
- // so we can treat 0 bytes read as EOF.
287
- // This is guaranteed by `ensure_capacity()` above
288
- // even if it is called with 0 as an argument.
289
- debug_assert ! ( !buf. is_empty( ) ) ;
290
-
291
- #[ cfg( feature = "runtime-async-std" ) ]
292
- let num_bytes_read = ready ! ( Pin :: new( & mut this. inner) . poll_read( cx, buf) ) ?;
293
-
294
- #[ cfg( feature = "runtime-tokio" ) ]
295
- let num_bytes_read = {
296
- let buf = & mut tokio:: io:: ReadBuf :: new ( buf) ;
297
- let start = buf. filled ( ) . len ( ) ;
298
- ready ! ( Pin :: new( & mut this. inner) . poll_read( cx, buf) ) ?;
299
- buf. filled ( ) . len ( ) - start
300
- } ;
301
-
302
- if num_bytes_read == 0 {
303
- if this. buffer . used ( ) > 0 {
304
- return Poll :: Ready ( Some ( Err ( io:: Error :: new (
305
- io:: ErrorKind :: UnexpectedEof ,
306
- "bytes remaining in stream" ,
307
- ) ) ) ) ;
308
- }
309
- return Poll :: Ready ( None ) ;
310
- }
311
- this. buffer . extend_used ( num_bytes_read) ;
312
- if let Some ( response) = this. decode ( ) ? {
313
- return Poll :: Ready ( Some ( Ok ( response) ) ) ;
335
+ let res = match ready ! ( self . as_mut( ) . do_poll_next( cx) ) {
336
+ None => None ,
337
+ Some ( Err ( err) ) => {
338
+ self . read_closed = true ;
339
+ Some ( Err ( err) )
314
340
}
315
- }
341
+ Some ( Ok ( item) ) => Some ( Ok ( item) ) ,
342
+ } ;
343
+ Poll :: Ready ( res)
316
344
}
317
345
}
318
346
0 commit comments