@@ -686,6 +686,10 @@ impl ReaderBuilder {
686
686
/// [`ReaderBuilder`](struct.ReaderBuilder.html).
687
687
/// * When reading CSV data from a resource (like a file), it is possible for
688
688
/// reading from the underlying resource to fail. This will return an error.
689
+ /// For subsequent calls to the `Reader` after encountering a such error
690
+ /// (unless `seek` is used), it will behave as if end of file had been
691
+ /// reached, in order to avoid running into infinite loops when still
692
+ /// attempting to read the next record when one has errored.
689
693
/// * When reading CSV data into `String` or `&str` fields (e.g., via a
690
694
/// [`StringRecord`](struct.StringRecord.html)), UTF-8 is strictly
691
695
/// enforced. If CSV data is invalid UTF-8, then an error is returned. If
@@ -741,7 +745,34 @@ struct ReaderState {
741
745
/// Whether the reader has been seeked or not.
742
746
seeked : bool ,
743
747
/// Whether EOF of the underlying reader has been reached or not.
744
- eof : bool ,
748
+ ///
749
+ /// IO errors on the underlying reader will be considered as an EOF for
750
+ /// subsequent read attempts, as it would be incorrect to keep on trying
751
+ /// to read when the underlying reader has broken.
752
+ ///
753
+ /// For clarity, having the best `Debug` impl and in case they need to be
754
+ /// treated differently at some point, we store whether the `EOF` is
755
+ /// considered because an actual EOF happened, or because we encoundered
756
+ /// an IO error.
757
+ /// This has no additional runtime cost.
758
+ eof : ReaderEofState ,
759
+ }
760
+
761
+ /// Whether EOF of the underlying reader has been reached or not.
762
+ ///
763
+ /// IO errors on the underlying reader will be considered as an EOF for
764
+ /// subsequent read attempts, as it would be incorrect to keep on trying
765
+ /// to read when the underlying reader has broken.
766
+ ///
767
+ /// For clarity, having the best `Debug` impl and in case they need to be
768
+ /// treated differently at some point, we store whether the `EOF` is
769
+ /// considered because an actual EOF happened, or because we encoundered
770
+ /// an IO error
771
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
772
+ enum ReaderEofState {
773
+ NotEof ,
774
+ Eof ,
775
+ IOError ,
745
776
}
746
777
747
778
/// Headers encapsulates any data associated with the headers of CSV data.
@@ -798,7 +829,7 @@ impl<R: io::Read> Reader<R> {
798
829
cur_pos : Position :: new ( ) ,
799
830
first : false ,
800
831
seeked : false ,
801
- eof : false ,
832
+ eof : ReaderEofState :: NotEof ,
802
833
} ,
803
834
}
804
835
}
@@ -1598,13 +1629,17 @@ impl<R: io::Read> Reader<R> {
1598
1629
1599
1630
record. clear ( ) ;
1600
1631
record. set_position ( Some ( self . state . cur_pos . clone ( ) ) ) ;
1601
- if self . state . eof {
1632
+ if self . state . eof != ReaderEofState :: NotEof {
1602
1633
return Ok ( false ) ;
1603
1634
}
1604
1635
let ( mut outlen, mut endlen) = ( 0 , 0 ) ;
1605
1636
loop {
1606
1637
let ( res, nin, nout, nend) = {
1607
- let input = self . rdr . fill_buf ( ) ?;
1638
+ let input_res = self . rdr . fill_buf ( ) ;
1639
+ if input_res. is_err ( ) {
1640
+ self . state . eof = ReaderEofState :: IOError ;
1641
+ }
1642
+ let input = input_res?;
1608
1643
let ( fields, ends) = record. as_parts ( ) ;
1609
1644
self . core . read_record (
1610
1645
input,
@@ -1636,7 +1671,7 @@ impl<R: io::Read> Reader<R> {
1636
1671
return Ok ( true ) ;
1637
1672
}
1638
1673
End => {
1639
- self . state . eof = true ;
1674
+ self . state . eof = ReaderEofState :: Eof ;
1640
1675
return Ok ( false ) ;
1641
1676
}
1642
1677
}
@@ -1716,7 +1751,7 @@ impl<R: io::Read> Reader<R> {
1716
1751
/// }
1717
1752
/// ```
1718
1753
pub fn is_done ( & self ) -> bool {
1719
- self . state . eof
1754
+ self . state . eof != ReaderEofState :: NotEof
1720
1755
}
1721
1756
1722
1757
/// Returns true if and only if this reader has been configured to
@@ -1817,7 +1852,7 @@ impl<R: io::Read + io::Seek> Reader<R> {
1817
1852
self . core . reset ( ) ;
1818
1853
self . core . set_line ( pos. line ( ) ) ;
1819
1854
self . state . cur_pos = pos;
1820
- self . state . eof = false ;
1855
+ self . state . eof = ReaderEofState :: NotEof ;
1821
1856
Ok ( ( ) )
1822
1857
}
1823
1858
@@ -1845,7 +1880,7 @@ impl<R: io::Read + io::Seek> Reader<R> {
1845
1880
self . core . reset ( ) ;
1846
1881
self . core . set_line ( pos. line ( ) ) ;
1847
1882
self . state . cur_pos = pos;
1848
- self . state . eof = false ;
1883
+ self . state . eof = ReaderEofState :: NotEof ;
1849
1884
Ok ( ( ) )
1850
1885
}
1851
1886
}
0 commit comments