@@ -10,7 +10,7 @@ use async_std::io::{Read, Write, WriteExt};
10
10
use base64:: Engine as _;
11
11
use extensions:: id:: { format_identification, parse_id} ;
12
12
use extensions:: quota:: parse_get_quota_root;
13
- use futures:: { io, Stream , StreamExt } ;
13
+ use futures:: { io, Stream , TryStreamExt } ;
14
14
use imap_proto:: { Metadata , RequestId , Response } ;
15
15
#[ cfg( feature = "runtime-tokio" ) ]
16
16
use tokio:: io:: { AsyncRead as Read , AsyncWrite as Write , AsyncWriteExt } ;
@@ -122,7 +122,7 @@ macro_rules! ok_or_unauth_client_err {
122
122
( $r: expr, $self: expr) => {
123
123
match $r {
124
124
Ok ( o) => o,
125
- Err ( e) => return Err ( ( e, $self) ) ,
125
+ Err ( e) => return Err ( ( e. into ( ) , $self) ) ,
126
126
}
127
127
} ;
128
128
}
@@ -262,42 +262,37 @@ impl<T: Read + Write + Unpin + fmt::Debug + Send> Client<T> {
262
262
// explicit match blocks neccessary to convert error to tuple and not bind self too
263
263
// early (see also comment on `login`)
264
264
loop {
265
- if let Some ( res) = self . read_response ( ) . await {
266
- let res = ok_or_unauth_client_err ! ( res. map_err( Into :: into) , self ) ;
267
- match res. parsed ( ) {
268
- Response :: Continue { information, .. } => {
269
- let challenge = if let Some ( text) = information {
270
- ok_or_unauth_client_err ! (
271
- base64:: engine:: general_purpose:: STANDARD
272
- . decode( text. as_ref( ) )
273
- . map_err( |e| Error :: Parse ( ParseError :: Authentication (
274
- ( * text) . to_string( ) ,
275
- Some ( e)
276
- ) ) ) ,
277
- self
278
- )
279
- } else {
280
- Vec :: new ( )
281
- } ;
282
- let raw_response = & mut authenticator. process ( & challenge) ;
283
- let auth_response =
284
- base64:: engine:: general_purpose:: STANDARD . encode ( raw_response) ;
285
-
286
- ok_or_unauth_client_err ! (
287
- self . conn. run_command_untagged( & auth_response) . await ,
288
- self
289
- ) ;
290
- }
291
- _ => {
265
+ let Some ( res) = ok_or_unauth_client_err ! ( self . read_response( ) . await , self ) else {
266
+ return Err ( ( Error :: ConnectionLost , self ) ) ;
267
+ } ;
268
+ match res. parsed ( ) {
269
+ Response :: Continue { information, .. } => {
270
+ let challenge = if let Some ( text) = information {
292
271
ok_or_unauth_client_err ! (
293
- self . check_done_ok_from( & id, None , res) . await ,
272
+ base64:: engine:: general_purpose:: STANDARD
273
+ . decode( text. as_ref( ) )
274
+ . map_err( |e| Error :: Parse ( ParseError :: Authentication (
275
+ ( * text) . to_string( ) ,
276
+ Some ( e)
277
+ ) ) ) ,
294
278
self
295
- ) ;
296
- return Ok ( Session :: new ( self . conn ) ) ;
297
- }
279
+ )
280
+ } else {
281
+ Vec :: new ( )
282
+ } ;
283
+ let raw_response = & mut authenticator. process ( & challenge) ;
284
+ let auth_response =
285
+ base64:: engine:: general_purpose:: STANDARD . encode ( raw_response) ;
286
+
287
+ ok_or_unauth_client_err ! (
288
+ self . conn. run_command_untagged( & auth_response) . await ,
289
+ self
290
+ ) ;
291
+ }
292
+ _ => {
293
+ ok_or_unauth_client_err ! ( self . check_done_ok_from( & id, None , res) . await , self ) ;
294
+ return Ok ( Session :: new ( self . conn ) ) ;
298
295
}
299
- } else {
300
- return Err ( ( Error :: ConnectionLost , self ) ) ;
301
296
}
302
297
}
303
298
}
@@ -975,12 +970,13 @@ impl<T: Read + Write + Unpin + fmt::Debug + Send> Session<T> {
975
970
mailbox_pattern. unwrap_or( "\" \" " )
976
971
) )
977
972
. await ?;
978
-
979
- Ok ( parse_names (
973
+ let names = parse_names (
980
974
& mut self . conn . stream ,
981
975
self . unsolicited_responses_tx . clone ( ) ,
982
976
id,
983
- ) )
977
+ ) ;
978
+
979
+ Ok ( names)
984
980
}
985
981
986
982
/// The [`LSUB` command](https://tools.ietf.org/html/rfc3501#section-6.3.9) returns a subset of
@@ -1136,23 +1132,20 @@ impl<T: Read + Write + Unpin + fmt::Debug + Send> Session<T> {
1136
1132
) )
1137
1133
. await ?;
1138
1134
1139
- match self . read_response ( ) . await {
1140
- Some ( Ok ( res) ) => {
1141
- if let Response :: Continue { .. } = res. parsed ( ) {
1142
- self . stream . as_mut ( ) . write_all ( content) . await ?;
1143
- self . stream . as_mut ( ) . write_all ( b"\r \n " ) . await ?;
1144
- self . stream . flush ( ) . await ?;
1145
- self . conn
1146
- . check_done_ok ( & id, Some ( self . unsolicited_responses_tx . clone ( ) ) )
1147
- . await ?;
1148
- Ok ( ( ) )
1149
- } else {
1150
- Err ( Error :: Append )
1151
- }
1152
- }
1153
- Some ( Err ( err) ) => Err ( err. into ( ) ) ,
1154
- _ => Err ( Error :: Append ) ,
1155
- }
1135
+ let Some ( res) = self . read_response ( ) . await ? else {
1136
+ return Err ( Error :: Append ) ;
1137
+ } ;
1138
+ let Response :: Continue { .. } = res. parsed ( ) else {
1139
+ return Err ( Error :: Append ) ;
1140
+ } ;
1141
+
1142
+ self . stream . as_mut ( ) . write_all ( content) . await ?;
1143
+ self . stream . as_mut ( ) . write_all ( b"\r \n " ) . await ?;
1144
+ self . stream . flush ( ) . await ?;
1145
+ self . conn
1146
+ . check_done_ok ( & id, Some ( self . unsolicited_responses_tx . clone ( ) ) )
1147
+ . await ?;
1148
+ Ok ( ( ) )
1156
1149
}
1157
1150
1158
1151
/// The [`SEARCH` command](https://tools.ietf.org/html/rfc3501#section-6.4.4) searches the
@@ -1352,7 +1345,7 @@ impl<T: Read + Write + Unpin + fmt::Debug + Send> Session<T> {
1352
1345
}
1353
1346
1354
1347
/// Read the next response on the connection.
1355
- pub async fn read_response ( & mut self ) -> Option < io:: Result < ResponseData > > {
1348
+ pub async fn read_response ( & mut self ) -> io:: Result < Option < ResponseData > > {
1356
1349
self . conn . read_response ( ) . await
1357
1350
}
1358
1351
}
@@ -1377,8 +1370,8 @@ impl<T: Read + Write + Unpin + fmt::Debug> Connection<T> {
1377
1370
}
1378
1371
1379
1372
/// Read the next response on the connection.
1380
- pub async fn read_response ( & mut self ) -> Option < io:: Result < ResponseData > > {
1381
- self . stream . next ( ) . await
1373
+ pub async fn read_response ( & mut self ) -> io:: Result < Option < ResponseData > > {
1374
+ self . stream . try_next ( ) . await
1382
1375
}
1383
1376
1384
1377
pub ( crate ) async fn run_command_untagged ( & mut self , command : & str ) -> Result < ( ) > {
@@ -1415,8 +1408,8 @@ impl<T: Read + Write + Unpin + fmt::Debug> Connection<T> {
1415
1408
id : & RequestId ,
1416
1409
unsolicited : Option < channel:: Sender < UnsolicitedResponse > > ,
1417
1410
) -> Result < ( ) > {
1418
- if let Some ( first_res) = self . stream . next ( ) . await {
1419
- self . check_done_ok_from ( id, unsolicited, first_res? ) . await
1411
+ if let Some ( first_res) = self . stream . try_next ( ) . await ? {
1412
+ self . check_done_ok_from ( id, unsolicited, first_res) . await
1420
1413
} else {
1421
1414
Err ( Error :: ConnectionLost )
1422
1415
}
@@ -1447,11 +1440,10 @@ impl<T: Read + Write + Unpin + fmt::Debug> Connection<T> {
1447
1440
handle_unilateral ( response, unsolicited) ;
1448
1441
}
1449
1442
1450
- if let Some ( res) = self . stream . next ( ) . await {
1451
- response = res?;
1452
- } else {
1443
+ let Some ( res) = self . stream . try_next ( ) . await ? else {
1453
1444
return Err ( Error :: ConnectionLost ) ;
1454
- }
1445
+ } ;
1446
+ response = res;
1455
1447
}
1456
1448
}
1457
1449
@@ -1495,6 +1487,7 @@ mod tests {
1495
1487
use std:: future:: Future ;
1496
1488
1497
1489
use async_std:: sync:: { Arc , Mutex } ;
1490
+ use futures:: StreamExt ;
1498
1491
use imap_proto:: Status ;
1499
1492
1500
1493
macro_rules! mock_client {
@@ -1555,7 +1548,7 @@ mod tests {
1555
1548
async fn readline_eof ( ) {
1556
1549
let mock_stream = MockStream :: default ( ) . with_eof ( ) ;
1557
1550
let mut client = mock_client ! ( mock_stream) ;
1558
- let res = client. read_response ( ) . await ;
1551
+ let res = client. read_response ( ) . await . unwrap ( ) ;
1559
1552
assert ! ( res. is_none( ) ) ;
1560
1553
}
1561
1554
@@ -2117,7 +2110,7 @@ mod tests {
2117
2110
. unwrap ( ) ;
2118
2111
2119
2112
// Unexpected EOF.
2120
- let err = fetch_result. next ( ) . await . unwrap ( ) . unwrap_err ( ) ;
2113
+ let err = fetch_result. try_next ( ) . await . unwrap_err ( ) ;
2121
2114
let Error :: Io ( io_err) = err else {
2122
2115
panic ! ( "Unexpected error type: {err}" )
2123
2116
} ;
0 commit comments