Description
I would like to use Bytes
to create parsers for binary formats. To report precise error messages, I would like to rely on Bytes::as_ptr() as usize
to get the current position in the main file. That works quite well ... except for when I run out of input. Consider the following example:
let b = Bytes::from_owner(b"Hi");
for i in 0..=b.len() {
let s = b.slice(i..);
let offset = dbg!(dbg!(s.as_ptr() as usize) - dbg!(b.as_ptr() as usize));
}
Here, the output is:
[src/main.rs:16:27] s.as_ptr() as usize = 101899852842091
[src/main.rs:16:55] b.as_ptr() as usize = 101899852842091
[src/main.rs:16:22] dbg!(s.as_ptr() as usize) - dbg!(b.as_ptr() as usize) = 0
[src/main.rs:16:27] s.as_ptr() as usize = 101899852842092
[src/main.rs:16:55] b.as_ptr() as usize = 101899852842091
[src/main.rs:16:22] dbg!(s.as_ptr() as usize) - dbg!(b.as_ptr() as usize) = 1
[src/main.rs:16:27] s.as_ptr() as usize = 1 <---------------------------------- !
[src/main.rs:16:55] b.as_ptr() as usize = 101899852842091
thread 'main' panicked at src/main.rs:16:27:
attempt to subtract with overflow
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
We can see that an empty Bytes
loses its offset. This is caused by the following code in Bytes::slice
:
if end == begin {
return Bytes::new();
}
This code also contradicts the current documentation for Bytes::slice
, which states:
This will increment the reference count for the underlying memory and return a new Bytes handle set to the slice.
I would like to propose the removal of the end == begin
check. Why?
Without this check in Bytes::slice
, a user of Bytes
can get the effect of this check by just doing the check manually before running Bytes::slice
. However, with this check in Bytes::slice
, it is impossible to disable it. Also, without this check, the behaviour of the function would automatically correspond to its documentation, which is currently not the case.