Vec
s support std::io::Write
, so code can be written that takes a File
or Vec
, for example. From the API reference, it looks like neither Vec
nor slices support std::io::Read
.
Is there a convenient way to achieve this? Does it require writing a wrapper struct?
Here is an example of working code, that reads and writes a file, with a single line commented that should read a vector.
use ::std::io; // Generic IO fn write_4_bytes<W>(mut file: W) -> Result<usize, io::Error> where W: io::Write, { let len = file.write(b"1234")?; Ok(len) } fn read_4_bytes<R>(mut file: R) -> Result<[u8; 4], io::Error> where R: io::Read, { let mut buf: [u8; 4] = [0; 4]; file.read(&mut buf)?; Ok(buf) } // Type specific fn write_read_vec() { let mut vec_as_file: Vec<u8> = Vec::new(); { // Write println!("Writing Vec... {}", write_4_bytes(&mut vec_as_file).unwrap()); } { // Read // println!("Reading File... {:?}", read_4_bytes(&vec_as_file).unwrap()); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // Comment this line above to avoid an error! } } fn write_read_file() { let filepath = "temp.txt"; { // Write let mut file_as_file = ::std::fs::File::create(filepath).expect("open failed"); println!("Writing File... {}", write_4_bytes(&mut file_as_file).unwrap()); } { // Read let mut file_as_file = ::std::fs::File::open(filepath).expect("open failed"); println!("Reading File... {:?}", read_4_bytes(&mut file_as_file).unwrap()); } } fn main() { write_read_vec(); write_read_file(); }
This fails with the error:
error[E0277]: the trait bound `std::vec::Vec<u8>: std::io::Read` is not satisfied --> src/main.rs:29:42 | 29 | println!("Reading File... {:?}", read_4_bytes(&vec_as_file).unwrap()); | ^^^^^^^^^^^^ the trait `std::io::Read` is not implemented for `std::vec::Vec<u8>` | = note: required by `read_4_bytes`
I'd like to write tests for a file format encoder/decoder, without having to write to the file-system.
The first and simplest method to read a file in Rust is to load it as an entire string. We can accomplish this using the std::fs::read_to_string method. The previous code imports the File struct and the prelude module. In the main function, we create a mutable variable called file and load open the arp.
Vector is a module in Rust that provides the container space to store values. It is a contiguous resizable array type, with heap-allocated contents. It is denoted by Vec<T>. Vectors in Rust have O(1) indexing and push and pop operations in vector also take O(1) complexity.
In Rust, there are several ways to initialize a vector. In order to initialize a vector via the new() method call, we use the double colon operator: let mut vec = Vec::new();
To remove all elements from a vector in Rust, use . retain() method to keep all elements the do not match. let mut v = vec![
While vectors don't support std::io::Read
, slices do.
There is some confusion here caused by Rust being able to coerce a Vec
into a slice in some situations but not others.
In this case, an explicit coercion to a slice is needed because at the stage coercions are applied, the compiler doesn't know that Vec<u8>
doesn't implement Read
.
The code in the question will work when the vector is coerced into a slice using one of the following methods:
read_4_bytes(&*vec_as_file)
read_4_bytes(&vec_as_file[..])
read_4_bytes(vec_as_file.as_slice())
.Note:
&Read
instead of Read
. This made passing a reference to a slice fail, unless I'd passed in &&*vec_as_file
which I didn't think to do.as_slice()
to convert a Vec to a slice.#rust
for finding the solution!If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With