如何在 BufReader 中包装同时实现读取和写入的结构的读取部分?

How can I wrap the read portion of a struct which implements both Read and Write in a BufReader?

提问人:curious 提问时间:3/16/2023 最后编辑:cafce25curious 更新时间:3/16/2023 访问量:106

问:

我正在尝试从对象中读取一行。我的第一反应是将它包装在一个 中,但问题是我需要能够将我的调用与调用交错,并且我不能使用底层流,同时对它有一个可变的引用。解决这个问题的惯用方法是什么?rustls::StreamOwnedBufReaderread_line()write()BufReader

示例代码:

let stream: rustls::StreamOwned = //blah
let r = BufReader::new(stream) // Can't pass a reference here since &rustls::StreamOwned doesn't implement the read trait
loop {
    let line: String;
    r.read_line(&line);
    stream.write(b"ping"); // Will fail to compile since r still owns the stream
}

类似问题:

如何将文件与BufReader一起使用并且仍然能够写入它?

不同之处在于,我正在处理的类型的引用类型没有实现该特征,因此我不能简单地将引用传递给 .ReadBufReader

rust borrow-checker borrow

评论

0赞 Chayim Friedman 3/16/2023
实现对类型的引用?ReadRefCell
0赞 curious 3/16/2023
@ChayimFriedman 你能提供一些示例代码吗?

答:

3赞 rodrigo 3/16/2023 #1

问题的解决方案来自不包含值的实现,而是实现 的泛型类型。在你的例子中,这是一个字面意思,实际类型不会丢失,因为你使用了BufReader,或者我应该说一个.BufReaderReadReadStreamOwnedBufReader<StreamOwned>

您可以使用 BufReader::get_mut() 访问内部值。文档中有一条注释说:

不建议直接从基础阅读器读取。

这是有道理的,因为直接读取会弄乱缓冲流,但它没有说明使用所包含对象的其他非读取功能,就像你的例子中写流的一半一样。

TL的;DR:写一些类似的东西(模拟的操场):

fn main() {
    let stream = StreamOwned;
    let mut r = BufReader::new(stream);
    loop {
        let mut line = String::new();
        r.read_line(&mut line);
        r.get_mut().write(b"ping"); // now it compiles!
    }
}

评论

0赞 curious 3/16/2023
是的,BufReader 包含“实现读取的类型”并没有混淆,因此我在最初的问题中写了“不实现读取特征”。 我理解为什么 BufReader 需要对底层阅读器的独占访问权限,但这不是我的问题。 确实是解决方案,但每次我想以可变方式使用它时,创建对基础对象的可变引用似乎有点笨拙。Which makes sense because that direct read would mess up the buffered stream,r.get_mut().write(b"ping");
0赞 rodrigo 3/16/2023
@curious:是的,我承认它看起来有点笨拙。如果你经常使用它,或者如果你想要一个 for it,那么创建一个 newtype 包装并实现 and for it 可能是有意义的。但对于常规使用,我认为这已经足够了BufWriterBufReader<StreamOwned>BufReadWrite