如何为rustls::StreamOwned包装BufReader并兼顾交替读写?
问题描述
我尝试从rustls::StreamOwned对象中读取一行内容,第一反应是用BufReader对其进行包装,但遇到两个问题:
- 当
BufReader持有流的所有权时,无法直接使用底层流进行写入操作; &rustls::StreamOwned(不可变引用)未实现Readtrait,无法直接将引用传入BufReader。
需要交替调用read_line()与write()方法,请问Rust的惯用解决方法是什么?
示例代码(编译失败):
let stream: rustls::StreamOwned = // 初始化逻辑 let r = BufReader::new(stream); // 无法传入引用,因为&StreamOwned未实现Read loop { let line: String; r.read_line(&line); stream.write(b"ping"); // 编译失败,因为stream的所有权已被r持有 }
解决方案
Rust中处理这类同步读写交替场景的惯用方法是利用BufReader提供的get_mut()方法,获取底层流的可变引用进行写入操作,同时保留BufReader的缓冲区管理能力。
方法说明
BufReader::new(stream)会获取StreamOwned的所有权,负责维护读取缓冲区;BufReader::get_mut()可以返回底层流的可变引用&mut StreamOwned,该引用实现了Writetrait,可直接用于写入;- 如果后续需要完全取回流的所有权,可使用
BufReader::into_inner()方法。
修正后的代码示例
use std::io::{BufRead, BufReader, Write}; use rustls::StreamOwned; fn main() { // 初始化你的rustls流 let mut stream: StreamOwned = /* 此处替换为实际的流初始化代码 */; // 用BufReader包裹流,获取所有权 let mut buf_reader = BufReader::new(stream); loop { let mut line = String::new(); match buf_reader.read_line(&mut line) { // 读取到0字节表示流已关闭 Ok(0) => break, Ok(_) => { // 获取底层流的可变引用进行写入 let underlying_stream = buf_reader.get_mut(); // 写入数据并flush确保发送 if let Err(e) = underlying_stream.write_all(b"ping\n") { eprintln!("写入失败: {}", e); break; } if let Err(e) = underlying_stream.flush() { eprintln!("刷新缓冲区失败: {}", e); break; } } Err(e) => { eprintln!("读取失败: {}", e); break; } } } // 若后续需要单独使用流,可通过into_inner取回所有权 let _reclaimed_stream = buf_reader.into_inner().unwrap(); }
补充说明
&mut StreamOwned是自动实现Readtrait的(标准库为所有实现Read的类型提供了&mut T的Read实现),但不可变引用&StreamOwned确实无法实现Read——因为Read的核心方法read需要修改流的内部状态,必须持有可变引用。- 避免每次循环重新创建
BufReader,否则会丢失缓冲区中的未读取数据,导致读取逻辑错误。
内容的提问来源于stack exchange,提问作者curious
相关产品推荐
相关产品推荐

