@@ -9,7 +9,8 @@ use chrono::{DateTime, Utc};
9
9
use regex:: Regex ;
10
10
11
11
use tokio:: io:: {
12
- copy, AsyncBufReadExt , AsyncRead , AsyncReadExt , AsyncWriteExt , BufReader , BufWriter ,
12
+ copy, AsyncBufRead , AsyncBufReadExt , AsyncRead , AsyncReadExt , AsyncWriteExt , BufReader ,
13
+ BufWriter ,
13
14
} ;
14
15
use tokio:: net:: { TcpStream , ToSocketAddrs } ;
15
16
@@ -435,12 +436,20 @@ impl FtpStream {
435
436
open_code : u32 ,
436
437
close_code : & [ u32 ] ,
437
438
) -> Result < Vec < String > > {
438
- let mut lines: Vec < String > = Vec :: new ( ) ;
439
-
440
- let mut data_stream = BufReader :: new ( self . data_command ( & cmd) . await ?) ;
439
+ let data_stream = BufReader :: new ( self . data_command ( & cmd) . await ?) ;
441
440
self . read_response_in ( & [ open_code, status:: ALREADY_OPEN ] )
442
441
. await ?;
442
+ let lines = Self :: get_lines_from_stream ( data_stream) . await ?;
443
+ self . read_response_in ( close_code) . await ?;
444
+ Ok ( lines)
445
+ }
443
446
447
+ /// Consume a stream and return a vector of lines
448
+ async fn get_lines_from_stream < R > ( mut data_stream : R ) -> Result < Vec < String > >
449
+ where
450
+ R : AsyncBufRead + Unpin ,
451
+ {
452
+ let mut lines: Vec < String > = Vec :: new ( ) ;
444
453
let mut line = String :: new ( ) ;
445
454
loop {
446
455
match data_stream. read_to_string ( & mut line) . await {
@@ -453,9 +462,6 @@ impl FtpStream {
453
462
Err ( err) => return Err ( FtpError :: ConnectionError ( err) ) ,
454
463
} ;
455
464
}
456
- drop ( data_stream) ;
457
-
458
- self . read_response_in ( close_code) . await ?;
459
465
Ok ( lines)
460
466
}
461
467
@@ -597,3 +603,37 @@ impl FtpStream {
597
603
}
598
604
}
599
605
}
606
+
607
+ #[ cfg( test) ]
608
+ mod tests {
609
+ use super :: FtpStream ;
610
+ use tokio:: { io:: stream_reader, stream} ;
611
+
612
+ #[ tokio:: test]
613
+ async fn list_command_dos_newlines ( ) {
614
+ let data_stream = stream_reader ( stream:: once ( Ok (
615
+ b"Hello\r \n World\r \n \r \n Be\r \n Happy\r \n " as & [ u8 ]
616
+ ) ) ) ;
617
+
618
+ assert_eq ! (
619
+ FtpStream :: get_lines_from_stream( data_stream) . await . unwrap( ) ,
620
+ [ "Hello" , "World" , "Be" , "Happy" ]
621
+ . iter( )
622
+ . map( <& str >:: to_string)
623
+ . collect:: <Vec <_>>( )
624
+ ) ;
625
+ }
626
+
627
+ #[ tokio:: test]
628
+ async fn list_command_unix_newlines ( ) {
629
+ let data_stream = stream_reader ( stream:: once ( Ok ( b"Hello\n World\n \n Be\n Happy\n " as & [ u8 ] ) ) ) ;
630
+
631
+ assert_eq ! (
632
+ FtpStream :: get_lines_from_stream( data_stream) . await . unwrap( ) ,
633
+ [ "Hello" , "World" , "Be" , "Happy" ]
634
+ . iter( )
635
+ . map( <& str >:: to_string)
636
+ . collect:: <Vec <_>>( )
637
+ ) ;
638
+ }
639
+ }
0 commit comments