rust/library
bors e68f935117 Auto merge of #98943 - WilliamVenner:feat/bufread_skip_until, r=dtolnay
Add `BufRead::skip_until`

Alternative version of `BufRead::read_until` that simply discards data, rather than copying it into a buffer.

Useful for situations like skipping irrelevant data in a binary file format that is NUL-terminated.

<details>
<summary>Benchmark</summary>

```
running 2 tests
test bench_read_until ... bench:         123 ns/iter (+/- 6)
test bench_skip_until ... bench:          66 ns/iter (+/- 3)
```

```rs
#![feature(test)]
extern crate test;
use test::Bencher;

use std::io::{ErrorKind, BufRead};

fn skip_until<R: BufRead + ?Sized>(r: &mut R, delim: u8) -> Result<usize, std::io::Error> {
    let mut read = 0;
    loop {
        let (done, used) = {
            let available = match r.fill_buf() {
                Ok(n) => n,
                Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
                Err(e) => return Err(e),
            };
            match memchr::memchr(delim, available) {
                Some(i) => (true, i + 1),
                None => (false, available.len()),
            }
        };
        r.consume(used);
        read += used;
        if done || used == 0 {
            return Ok(read);
        }
    }
}

const STR: &[u8] = b"Ferris\0Hello, world!\0";

#[bench]
fn bench_skip_until(b: &mut Bencher) {
    b.iter(|| {
        let mut io = std::io::Cursor::new(test::black_box(STR));
        skip_until(&mut io, b'\0').unwrap();
        let mut hello = Vec::with_capacity(b"Hello, world!\0".len());
        let num_bytes = io.read_until(b'\0', &mut hello).unwrap();
        assert_eq!(num_bytes, b"Hello, world!\0".len());
        assert_eq!(hello, b"Hello, world!\0");
    });
}

#[bench]
fn bench_read_until(b: &mut Bencher) {
    b.iter(|| {
        let mut io = std::io::Cursor::new(test::black_box(STR));
        io.read_until(b'\0', &mut Vec::new()).unwrap();
        let mut hello = Vec::with_capacity(b"Hello, world!\0".len());
        let num_bytes = io.read_until(b'\0', &mut hello).unwrap();
        assert_eq!(num_bytes, b"Hello, world!\0".len());
        assert_eq!(hello, b"Hello, world!\0");
    });
}
```
</details>
2023-11-23 22:28:14 +00:00
..
alloc docs(GH-118094): make docs a bit more explicit 2023-11-20 18:35:04 +03:00
backtrace@6145fe6bac Update backtrace submodule 2023-11-21 16:33:42 +01:00
core Stabilize RFC3324 dyn upcasting coercion 2023-11-22 13:56:36 +01:00
panic_abort Rebase to master 2023-09-22 17:23:33 +05:30
panic_unwind Use pointers instead of usize addresses for landing pads 2023-10-10 09:59:39 +02:00
portable-simd use visibility to check unused imports and delete some stmts 2023-10-22 21:27:46 +08:00
proc_macro Bump cfg(bootstrap)s 2023-11-15 19:41:28 -05:00
profiler_builtins Bump cfg(bootstrap) 2023-08-23 20:05:14 -04:00
rtstartup Remove custom frame info registration on i686-pc-windows-gnu 2022-08-23 16:12:58 +08:00
rustc-std-workspace-alloc Replace libstd, libcore, liballoc in line comments. 2022-12-30 14:00:42 +01:00
rustc-std-workspace-core
rustc-std-workspace-std
std Auto merge of #98943 - WilliamVenner:feat/bufread_skip_until, r=dtolnay 2023-11-23 22:28:14 +00:00
stdarch@f4528dd6e8 Bump stdarch submodule 2023-10-12 11:11:29 +02:00
sysroot Expose compiler-builtins-weak-intrinsics feature for -Zbuild-std 2023-06-23 11:15:34 +01:00
test Bump cfg(bootstrap)s 2023-11-15 19:41:28 -05:00
unwind Remove obsolete support for linking unwinder on Android 2023-11-02 18:06:35 -07:00