@@ -4,14 +4,14 @@ use log::{debug, warn};
4
4
use rouille:: url:: Url ;
5
5
use serde:: { Deserialize , Serialize } ;
6
6
use serde_json:: { json, Map , Value as Json } ;
7
- use std:: env;
8
7
use std:: fs:: File ;
9
- use std:: io:: { BufRead , BufReader , Read } ;
8
+ use std:: io:: { Cursor , Read , Write } ;
10
9
use std:: net:: { SocketAddr , TcpListener , TcpStream } ;
11
10
use std:: path:: { Path , PathBuf } ;
12
11
use std:: process:: { Child , ChildStderr , ChildStdout , Command , Stdio } ;
13
12
use std:: thread;
14
13
use std:: time:: { Duration , Instant } ;
14
+ use std:: { env, io} ;
15
15
use ureq:: Agent ;
16
16
17
17
/// Options that can use to customize and configure a WebDriver session.
@@ -627,12 +627,46 @@ fn tab(s: &str) -> String {
627
627
628
628
struct BackgroundChild < ' a > {
629
629
child : Child ,
630
- stdout : BufReader < ChildStdout > ,
631
- stderr : BufReader < ChildStderr > ,
630
+ stdout : ReadCache < ChildStdout > ,
631
+ stderr : ReadCache < ChildStderr > ,
632
632
shell : & ' a Shell ,
633
633
print_stdio_on_drop : bool ,
634
634
}
635
635
636
+ struct ReadCache < T > {
637
+ source : T ,
638
+ buffer : Cursor < Vec < u8 > > ,
639
+ }
640
+
641
+ impl < T : Read > ReadCache < T > {
642
+ fn new ( source : T ) -> Self {
643
+ Self {
644
+ source,
645
+ buffer : Cursor :: new ( Vec :: new ( ) ) ,
646
+ }
647
+ }
648
+
649
+ fn has_data ( & mut self ) -> bool {
650
+ if self . buffer . position ( ) != 0 {
651
+ return true ;
652
+ }
653
+
654
+ let mut buffer = [ 0 ] ;
655
+
656
+ if self . source . read ( & mut buffer) . unwrap ( ) == 1 {
657
+ self . buffer . write_all ( & buffer) . unwrap ( ) ;
658
+ true
659
+ } else {
660
+ false
661
+ }
662
+ }
663
+
664
+ fn read_to_end ( & mut self ) -> & [ u8 ] {
665
+ io:: copy ( & mut self . source , & mut self . buffer ) . unwrap ( ) ;
666
+ self . buffer . get_ref ( )
667
+ }
668
+ }
669
+
636
670
impl < ' a > BackgroundChild < ' a > {
637
671
fn spawn (
638
672
path : & Path ,
@@ -646,8 +680,8 @@ impl<'a> BackgroundChild<'a> {
646
680
let mut child = cmd
647
681
. spawn ( )
648
682
. context ( format ! ( "failed to spawn {:?} binary" , path) ) ?;
649
- let stdout = BufReader :: new ( child. stdout . take ( ) . unwrap ( ) ) ;
650
- let stderr = BufReader :: new ( child. stderr . take ( ) . unwrap ( ) ) ;
683
+ let stdout = ReadCache :: new ( child. stdout . take ( ) . unwrap ( ) ) ;
684
+ let stderr = ReadCache :: new ( child. stderr . take ( ) . unwrap ( ) ) ;
651
685
Ok ( BackgroundChild {
652
686
child,
653
687
stdout,
@@ -660,11 +694,7 @@ impl<'a> BackgroundChild<'a> {
660
694
fn has_failed ( & mut self ) -> bool {
661
695
match self . child . try_wait ( ) {
662
696
Ok ( Some ( status) ) => !status. success ( ) ,
663
- Ok ( None ) => self
664
- . stderr
665
- . fill_buf ( )
666
- . map ( |b| !b. is_empty ( ) )
667
- . unwrap_or ( true ) ,
697
+ Ok ( None ) => self . stderr . has_data ( ) ,
668
698
Err ( _) => true ,
669
699
}
670
700
}
@@ -681,15 +711,13 @@ impl Drop for BackgroundChild<'_> {
681
711
self . shell . clear ( ) ;
682
712
println ! ( "driver status: {}" , status) ;
683
713
684
- let mut stdout = Vec :: new ( ) ;
685
- self . stdout . read_to_end ( & mut stdout) . unwrap ( ) ;
714
+ let stdout = self . stdout . read_to_end ( ) ;
686
715
if !stdout. is_empty ( ) {
687
- println ! ( "driver stdout:\n {}" , tab( & String :: from_utf8_lossy( & stdout) ) ) ;
716
+ println ! ( "driver stdout:\n {}" , tab( & String :: from_utf8_lossy( stdout) ) ) ;
688
717
}
689
- let mut stderr = Vec :: new ( ) ;
690
- self . stderr . read_to_end ( & mut stderr) . unwrap ( ) ;
718
+ let stderr = self . stderr . read_to_end ( ) ;
691
719
if !stderr. is_empty ( ) {
692
- println ! ( "driver stderr:\n {}" , tab( & String :: from_utf8_lossy( & stderr) ) ) ;
720
+ println ! ( "driver stderr:\n {}" , tab( & String :: from_utf8_lossy( stderr) ) ) ;
693
721
}
694
722
}
695
723
}
0 commit comments