Cannot use BufRead.consume()


#1

I’m trying to use BufRead.fill_buf()/consume().

My idea is this: if buffer contains enough bytes, I can read from contiguous memory area which is very fast. Otherwize I have to deal with buffer refills.

(In this example I’m reading bytes until nonzero, but actually I need to read varint).

So, code should look like this:

// read byte-after-byte
fn read_slow(r: &mut BufRead) -> io::Result<u32> {
    let mut count = 0;
    loop {
        let mut buf = [0; 1];
        try!(r.read_exact(&mut buf));
        if buf[0] != 0 {
            return Ok((count));
        }
        count += 1;
    }
}

fn read(r: &mut BufRead) -> io::Result<u32> {
    let buf = try!(r.fill_buf());
    
    // fast path
    let mut count = 0;
    for &c in buf {
        if c != 0 {
            drop(buf); // does not help
            r.consume(count as usize); // does not work
            return Ok((count));
        }
        count += 1;
    }
    
    // does not work either
    read_slow(r)
}

It does not work. Rust does not allow me to call consume because buf is borrowed. And there’s no easy was to just unborrow it even if I don’t need it anymore.

As far as I understand, the problem is with lexical borrowing. Is it going to fixed any time soon?

Or maybe I’m missing some obvious workaround?

Play


#2

Will something like this work? http://is.gd/Hlt5Vr


#3

@matklad thanks!


#4

Thanks for rust-protobuf! Curiously enough, I’ve myself written the code to extract a leading varint from buffer (I was unable to fully reuse rust-protobuf implementation, because buffers were used in async context). It is ugly, slow and quite probably wrong, but here it is, just in case: https://github.com/matklad/auchat/blob/master/src/proto_reader.rs#L27