Why does `[u8;1]` does not implement the read trait?

Just a simple question, for which I don't seem to find an answer.
Is there any reason why an array (with a fixed size), doesn't implement the std::io::Read trait, while a slice does implement it?

The following code doesn't work:

fn sample<R: std::io::Read>(reader: R) {}

fn main() {
    let x = [0x00] as [u8; 1];
    sample(x);
}

While the following code does work:

fn sample<R: std::io::Read>(reader: R) {}

fn main() {
    let x: &[u8] = &[0x00];
    sample(x);
}

The Read trait has as a primary method

fn read(&mut self, buf: &mut [u8]) -> Result<usize>

that operates on a mutable object. The implementor of Read has to keep track of which bytes are and aren’t consumed yet. The implementation for &[u8] does this by an implementation for &[u8] references, not for [u8] directly:

fn read(self: &mut &[u8], buf: &mut [u8]) -> Result<usize>

resulting in a nested reference type. The implementation the operates by modifying the &[u8] behind the mutable reference, by trimming the slice to the remaining unconsumed part.

Here’s the implementation. Note the *self = b; line, where b comes from let (a, b) = self.split_at(amt);

You can use an array for io::Read if you augment it by some state tracking the position. This is exactly what Cursor can do. So just use Cursor<[u8; 1]> I guess?

4 Likes

Thanks for the clear explanation. It makes sense now.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.