It boils down to what sorts of problems can happen if the trait implementation is buggy. Rust's rule of thumb is that all unsoundness is caused by unsafe
code, and that outside of unsafe
code, bugs must never be able to cause undefined behaviour.
Thus, if you're writing unsafe
code, interacting with Read::read
, and n > buf.len()
, you can generate an error, or return nonsense values. You can't overflow the buffer, or read out of bounds as a result - it's on you to ensure that the return value is in-bounds.
So, as an example, if I write:
let data = vec![0;256];
let bytes_read = input.read(&mut data)?;
unsafe {
data.get_unchecked(bytes_read / 2)
}
I've done something wrong - if input
's implementation of read
is buggy, then I could attempt an out-of-bounds read (e.g. if bytes_read
was 1024), and the documentation is making it clear that the consequences of that out-of-bound read are my fault.
On the other hand, if I write:
let data = vec![0;256];
let bytes_read = input.read(&mut data)?;
data.get(bytes_read / 2).expect("bytes_read was out of bounds")
I'm no longer going to attempt an out-of-bounds read (because I'm using the checked variant of get
), and thus I'm OK.
If I wanted to, I could also write:
let data = vec![0;256];
let bytes_read = input.read(&mut data)?;
unsafe {
data.get_unchecked((data.len() / 2).min(bytes_read / 2))
}
This is also fine, because I ensure that the value is in-bounds before doing my read, but might still return nonsense (because the input.read
implementation was buggy).