NilsIrl
December 26, 2024, 6:57am
1
fn main() {
use std::io::{self, BufRead};
let mut cursor = io::Cursor::new(b"hell\n");
dbg!(cursor.skip_until(b'\n').unwrap());
let mut cursor = io::Cursor::new(b"hello");
dbg!(cursor.skip_until(b'\n').unwrap());
}
(Playground )
output:
[src/main.rs:5:5] cursor.skip_until(b'\n').unwrap() = 5
[src/main.rs:8:5] cursor.skip_until(b'\n').unwrap() = 5
How does one tell whether the skip_until()
function actually found the byte or not (without using functions outside of the BufRead
trait)?
You could use read_until
instead and look at the last byte.
NilsIrl
December 26, 2024, 7:46am
3
That works but it defeats the point of skip_until
which doesn't need to allocate memory to store data that won't be used.
I don't see any way clear way to accomplish that
The options to achieve it I see:
If you actually using cursor, use nightly BufRead in std::io - Rust
Implement read_until yourself, and tweak. There is std implementation:
fn skip_until<R: BufRead + ?Sized>(r: &mut R, delim: u8) -> Result<usize> {
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);
}
}
}
1 Like
NilsIrl
December 27, 2024, 1:38am
5
How would using has_data_left
be sufficient here? Because you could have a newline as the last byte in which case it is not possible to tell them apart.
rjc2013
December 28, 2024, 3:03am
6
If you don't mind one final read at the end, you could do it like this:
use std::io::{self, BufRead, Read, Seek};
fn main() {
let mut cursor = io::Cursor::new(b"hell\n");
dbg!(cursor.skip_until(b'\n').unwrap());
dbg!(prev_byte(&mut cursor) == Some(b'\n')); // true
let mut cursor = io::Cursor::new(b"hello");
dbg!(cursor.skip_until(b'\n').unwrap());
dbg!(prev_byte(&mut cursor) == Some(b'\n')); // false
}
fn prev_byte<R: Read + Seek>(mut r: R) -> Option<u8> {
r.seek_relative(-1).ok()?;
let mut buf = [0u8; 1];
r.read(&mut buf).ok()?;
Some(buf[0])
}
2 Likes