@@ -1923,6 +1923,28 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> R
1923
1923
}
1924
1924
}
1925
1925
1926
+ fn skip_until < R : BufRead + ?Sized > ( r : & mut R , delim : u8 ) -> Result < usize > {
1927
+ let mut read = 0 ;
1928
+ loop {
1929
+ let ( done, used) = {
1930
+ let available = match r. fill_buf ( ) {
1931
+ Ok ( n) => n,
1932
+ Err ( ref e) if e. kind ( ) == ErrorKind :: Interrupted => continue ,
1933
+ Err ( e) => return Err ( e) ,
1934
+ } ;
1935
+ match memchr:: memchr ( delim, available) {
1936
+ Some ( i) => ( true , i + 1 ) ,
1937
+ None => ( false , available. len ( ) ) ,
1938
+ }
1939
+ } ;
1940
+ r. consume ( used) ;
1941
+ read += used;
1942
+ if done || used == 0 {
1943
+ return Ok ( read) ;
1944
+ }
1945
+ }
1946
+ }
1947
+
1926
1948
/// A `BufRead` is a type of `Read`er which has an internal buffer, allowing it
1927
1949
/// to perform extra ways of reading.
1928
1950
///
@@ -2126,6 +2148,68 @@ pub trait BufRead: Read {
2126
2148
read_until ( self , byte, buf)
2127
2149
}
2128
2150
2151
+ /// Skip all bytes until the delimiter `byte` or EOF is reached.
2152
+ ///
2153
+ /// This function will read (and discard) bytes from the underlying stream until the
2154
+ /// delimiter or EOF is found.
2155
+ ///
2156
+ /// If successful, this function will return the total number of bytes read,
2157
+ /// including the delimiter byte.
2158
+ ///
2159
+ /// This is useful for efficiently skipping data such as NUL-terminated strings
2160
+ /// in binary file formats without buffering.
2161
+ ///
2162
+ /// This function is blocking and should be used carefully: it is possible for
2163
+ /// an attacker to continuously send bytes without ever sending the delimiter
2164
+ /// or EOF.
2165
+ ///
2166
+ /// # Errors
2167
+ ///
2168
+ /// This function will ignore all instances of [`ErrorKind::Interrupted`] and
2169
+ /// will otherwise return any errors returned by [`fill_buf`].
2170
+ ///
2171
+ /// If an I/O error is encountered then all bytes read so far will be
2172
+ /// present in `buf` and its length will have been adjusted appropriately.
2173
+ ///
2174
+ /// [`fill_buf`]: BufRead::fill_buf
2175
+ ///
2176
+ /// # Examples
2177
+ ///
2178
+ /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
2179
+ /// this example, we use [`Cursor`] to read some NUL-terminated information
2180
+ /// about Ferris from a binary string, skipping the fun fact:
2181
+ ///
2182
+ /// ```
2183
+ /// #![feature(bufread_skip_until)]
2184
+ ///
2185
+ /// use std::io::{self, BufRead};
2186
+ ///
2187
+ /// let mut cursor = io::Cursor::new(b"Ferris\0Likes long walks on the beach\0Crustacean\0");
2188
+ ///
2189
+ /// // read name
2190
+ /// let mut name = Vec::new();
2191
+ /// let num_bytes = cursor.read_until(b'\0', &mut name)
2192
+ /// .expect("reading from cursor won't fail");
2193
+ /// assert_eq!(num_bytes, 7);
2194
+ /// assert_eq!(name, b"Ferris\0");
2195
+ ///
2196
+ /// // skip fun fact
2197
+ /// let num_bytes = cursor.skip_until(b'\0')
2198
+ /// .expect("reading from cursor won't fail");
2199
+ /// assert_eq!(num_bytes, 30);
2200
+ ///
2201
+ /// // read animal type
2202
+ /// let mut animal = Vec::new();
2203
+ /// let num_bytes = cursor.read_until(b'\0', &mut animal)
2204
+ /// .expect("reading from cursor won't fail");
2205
+ /// assert_eq!(num_bytes, 11);
2206
+ /// assert_eq!(animal, b"Crustacean\0");
2207
+ /// ```
2208
+ #[ unstable( feature = "bufread_skip_until" , issue = "none" ) ]
2209
+ fn skip_until ( & mut self , byte : u8 ) -> Result < usize > {
2210
+ skip_until ( self , byte)
2211
+ }
2212
+
2129
2213
/// Read all bytes until a newline (the `0xA` byte) is reached, and append
2130
2214
/// them to the provided buffer. You do not need to clear the buffer before
2131
2215
/// appending.
0 commit comments