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();
}
Run Code Online (Sandbox Code Playgroud)
这失败并出现错误:
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`
Run Code Online (Sandbox Code Playgroud)
我想为文件格式编码器/解码器编写测试,而不必写入文件系统.
Ale*_*eev 24
std::io::Cursor是一个简单而有用的包装器,它实现了Readfor Vec<u8>,因此它允许使用 vector 作为可读实体。
let mut file = Cursor::new(vector);
read_something(&mut file);
Run Code Online (Sandbox Code Playgroud)
和文档展示了如何使用Cursor,而不是File来写单元测试!
工作示例:
use std::io::Cursor;
use std::io::Read;
fn read_something(file: &mut impl Read) {
let _ = file.read(&mut [0; 8]);
}
fn main() {
let vector = vec![1, 2, 3, 4];
let mut file = Cursor::new(vector);
read_something(&mut file);
}
Run Code Online (Sandbox Code Playgroud)
从文档有关std::io::Cursor:
游标通常与内存缓冲区一起使用,以允许它们实现
Read和/或Write...标准库在通常用作缓冲区的各种类型上实现了一些 I/O 特性,例如
Cursor<Vec<u8>>和Cursor<&[u8]>。
上面的例子也适用于切片。在这种情况下,它将如下所示:
read_something(&mut &vector[..]);
Run Code Online (Sandbox Code Playgroud)
工作示例:
use std::io::Read;
fn read_something(file: &mut impl Read) {
let _ = file.read(&mut [0; 8]);
}
fn main() {
let vector = vec![1, 2, 3, 4];
read_something(&mut &vector[..]);
}
Run Code Online (Sandbox Code Playgroud)
&mut &vector[..]是“对切片的可变引用”(对向量一部分的引用的引用),所以我只是发现显式选项 withCursor更清晰和优雅。
甚至更多:如果您有一个Cursor拥有缓冲区的 ,并且您需要模拟例如“文件”的一部分,您可以slice从 中获取 aCursor并传递给该函数。
read_something(&mut &file.get_ref()[1..3]);
Run Code Online (Sandbox Code Playgroud)
ide*_*n42 16
虽然矢量不支持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寻找解决方案!