Hone logo
Hone
Problems

Implementing the Read Trait in Rust

The Read trait in Rust provides a standard interface for reading data from a source, such as a file or a network connection. Implementing this trait allows your custom types to seamlessly integrate with existing Rust libraries that consume readers, enabling flexible data processing pipelines. This challenge asks you to implement the Read trait for a custom data source.

Problem Description

You are tasked with implementing the Read trait for a custom type called ByteStream. ByteStream represents a stream of bytes stored in a Vec<u8>. Your implementation should allow reading data from this stream using the read method of the Read trait.

What needs to be achieved:

  • Create a struct ByteStream that holds a Vec<u8> internally.
  • Implement the Read trait for ByteStream.
  • The read method should read data into a provided &mut ReadBuf.
  • The method should return the number of bytes actually read.

Key requirements:

  • The Read trait requires the ReadBuf type.
  • The read method should handle the case where the stream is exhausted (all bytes have been read).
  • The read method should return the correct number of bytes read.
  • The read method should not panic if the stream is exhausted.

Expected behavior:

When read is called, it should attempt to fill the provided ReadBuf with bytes from the ByteStream. If there are enough bytes available, it should copy them into the buffer and return the number of bytes copied. If the stream is exhausted, it should return 0.

Edge cases to consider:

  • Empty ByteStream (Vec<u8> is empty).
  • ReadBuf with a capacity of 0.
  • Requesting to read more bytes than are available in the ByteStream.

Examples

Example 1:

Input: ByteStream(vec![1, 2, 3, 4, 5]), ReadBuf::new(vec![0u8; 3])
Output: 3
Explanation: The first 3 bytes (1, 2, 3) are read into the ReadBuf. The ReadBuf now contains [1, 2, 3].

Example 2:

Input: ByteStream(vec![1, 2]), ReadBuf::new(vec![0u8; 3])
Output: 2
Explanation: Only 2 bytes are available, so they are read into the ReadBuf. The ReadBuf now contains [1, 2, 0].

Example 3:

Input: ByteStream(vec![]), ReadBuf::new(vec![0u8; 3])
Output: 0
Explanation: The ByteStream is empty, so no bytes are read. The ReadBuf remains unchanged.

Constraints

  • The ByteStream will always contain valid u8 values.
  • The ReadBuf will always have a non-negative capacity.
  • Performance is not a primary concern for this challenge; correctness is paramount.
  • The solution must compile and pass all test cases.

Notes

  • Remember to use the ReadBuf's fill_mut method to copy data into the buffer.
  • Consider using a mutable reference to the internal Vec<u8> to track the current read position.
  • The Read trait is defined in the std::io module. You'll need to bring it into scope.
  • Think about how to handle the case where the requested number of bytes is greater than the remaining bytes in the stream.
use std::io::{Read, ReadBuf};

struct ByteStream(Vec<u8>);

impl Read for ByteStream {
    fn read(&mut self, buf: &mut ReadBuf<'_>) -> std::io::Result<usize> {
        let available = self.0.len();
        let mut bytes_read = 0;

        if available == 0 {
            return Ok(0);
        }

        let to_read = std::cmp::min(available, buf.capacity());

        if to_read > 0 {
            bytes_read = buf.fill_mut(&self.0[..to_read]);
            self.0.drain(..to_read); // Remove the read bytes
        }

        Ok(bytes_read)
    }
}
Loading editor...
rust