@@ -2044,6 +2044,28 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> R
20442044 }
20452045}
20462046
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+
20472069/// A `BufRead` is a type of `Read`er which has an internal buffer, allowing it
20482070/// to perform extra ways of reading.
20492071///
@@ -2247,6 +2269,68 @@ pub trait BufRead: Read {
22472269 read_until ( self , byte, buf)
22482270 }
22492271
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+
22502334 /// Read all bytes until a newline (the `0xA` byte) is reached, and append
22512335 /// them to the provided `String` buffer.
22522336 ///
0 commit comments