@@ -2044,6 +2044,28 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> R
2044
2044
}
2045
2045
}
2046
2046
2047
+ fn skip_until < R : BufRead + ?Sized > ( r : & mut R , delim : u8 ) -> Result < usize > {
2048
+ let mut read = 0 ;
2049
+ loop {
2050
+ let ( done, used) = {
2051
+ let available = match r. fill_buf ( ) {
2052
+ Ok ( n) => n,
2053
+ Err ( ref e) if e. kind ( ) == ErrorKind :: Interrupted => continue ,
2054
+ Err ( e) => return Err ( e) ,
2055
+ } ;
2056
+ match memchr:: memchr ( delim, available) {
2057
+ Some ( i) => ( true , i + 1 ) ,
2058
+ None => ( false , available. len ( ) ) ,
2059
+ }
2060
+ } ;
2061
+ r. consume ( used) ;
2062
+ read += used;
2063
+ if done || used == 0 {
2064
+ return Ok ( read) ;
2065
+ }
2066
+ }
2067
+ }
2068
+
2047
2069
/// A `BufRead` is a type of `Read`er which has an internal buffer, allowing it
2048
2070
/// to perform extra ways of reading.
2049
2071
///
@@ -2247,6 +2269,68 @@ pub trait BufRead: Read {
2247
2269
read_until ( self , byte, buf)
2248
2270
}
2249
2271
2272
+ /// Skip all bytes until the delimiter `byte` or EOF is reached.
2273
+ ///
2274
+ /// This function will read (and discard) bytes from the underlying stream until the
2275
+ /// delimiter or EOF is found.
2276
+ ///
2277
+ /// If successful, this function will return the total number of bytes read,
2278
+ /// including the delimiter byte.
2279
+ ///
2280
+ /// This is useful for efficiently skipping data such as NUL-terminated strings
2281
+ /// in binary file formats without buffering.
2282
+ ///
2283
+ /// This function is blocking and should be used carefully: it is possible for
2284
+ /// an attacker to continuously send bytes without ever sending the delimiter
2285
+ /// or EOF.
2286
+ ///
2287
+ /// # Errors
2288
+ ///
2289
+ /// This function will ignore all instances of [`ErrorKind::Interrupted`] and
2290
+ /// will otherwise return any errors returned by [`fill_buf`].
2291
+ ///
2292
+ /// If an I/O error is encountered then all bytes read so far will be
2293
+ /// present in `buf` and its length will have been adjusted appropriately.
2294
+ ///
2295
+ /// [`fill_buf`]: BufRead::fill_buf
2296
+ ///
2297
+ /// # Examples
2298
+ ///
2299
+ /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
2300
+ /// this example, we use [`Cursor`] to read some NUL-terminated information
2301
+ /// about Ferris from a binary string, skipping the fun fact:
2302
+ ///
2303
+ /// ```
2304
+ /// #![feature(bufread_skip_until)]
2305
+ ///
2306
+ /// use std::io::{self, BufRead};
2307
+ ///
2308
+ /// let mut cursor = io::Cursor::new(b"Ferris\0Likes long walks on the beach\0Crustacean\0");
2309
+ ///
2310
+ /// // read name
2311
+ /// let mut name = Vec::new();
2312
+ /// let num_bytes = cursor.read_until(b'\0', &mut name)
2313
+ /// .expect("reading from cursor won't fail");
2314
+ /// assert_eq!(num_bytes, 7);
2315
+ /// assert_eq!(name, b"Ferris\0");
2316
+ ///
2317
+ /// // skip fun fact
2318
+ /// let num_bytes = cursor.skip_until(b'\0')
2319
+ /// .expect("reading from cursor won't fail");
2320
+ /// assert_eq!(num_bytes, 30);
2321
+ ///
2322
+ /// // read animal type
2323
+ /// let mut animal = Vec::new();
2324
+ /// let num_bytes = cursor.read_until(b'\0', &mut animal)
2325
+ /// .expect("reading from cursor won't fail");
2326
+ /// assert_eq!(num_bytes, 11);
2327
+ /// assert_eq!(animal, b"Crustacean\0");
2328
+ /// ```
2329
+ #[ unstable( feature = "bufread_skip_until" , issue = "111735" ) ]
2330
+ fn skip_until ( & mut self , byte : u8 ) -> Result < usize > {
2331
+ skip_until ( self , byte)
2332
+ }
2333
+
2250
2334
/// Read all bytes until a newline (the `0xA` byte) is reached, and append
2251
2335
/// them to the provided `String` buffer.
2252
2336
///
0 commit comments