如何从Vec或Slice读取(std :: io :: Read)? [英] How to read (std::io::Read) from a Vec or Slice?
问题描述
Vec
支持std::io::Write
,因此可以编写采用File
或Vec
的代码.从API参考来看,Vec
和切片都不支持std::io::Read
.
是否有实现此目的的便捷方法?是否需要编写包装器结构?
这里是工作代码的示例,该文件读写文件,并带有注释的一行应读取向量.
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();
}
此操作失败,并显示以下错误:
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`
我想为文件格式编码器/解码器编写测试,而不必写入文件系统.
向量不支持std::io::Read
,而切片支持.
在某些情况下,Rust能够将Vec
强制转换为切片,这引起了一些混乱.
在这种情况下,需要对切片进行显式强制,因为在施加阶段强制时,编译器不知道Vec<u8>
没有实现Read
.>
将向量强制转换为切片时,问题中的代码将起作用,例如:read_4_bytes(&*vec_as_file)
或read_4_bytes(&vec_as_file[..])
.
注意:
- 最初询问问题时,我服用的是
&Read
而不是Read
.这使传递对切片的引用失败,除非我传递了我不认为要做的&&*vec_as_file
. - 感谢
#rust
上的@arete查找解决方案!
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.
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, either as: read_4_bytes(&*vec_as_file)
or read_4_bytes(&vec_as_file[..])
.
Note:
- When asking the question initially, I was taking
&Read
instead ofRead
. This made passing a reference to a slice fail, unless I'd passed in&&*vec_as_file
which I didn't think to do. - Thanks to @arete on
#rust
for finding the solution!
这篇关于如何从Vec或Slice读取(std :: io :: Read)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!