rust - Rust:将流读入缓冲区直到它“完成”
问题描述
我有一段代码使用以下模式:
let mut request_buf: Vec<u8> = vec![];
let mut buf = [0 as u8; 50]; // 50 byte read buffer
while !req.parse(&request_buf).unwrap().is_complete() {
match stream.read(&mut buf) {
Ok(size) => {
request_buf.extend(&buf[0..size]);
},
Err(_) => {
// Handle err...
}
}
}
基本上,代码应该从套接字读取数据到临时缓冲区buf
并累积它直到 fn is_complete() 返回 true。
我遇到了借用检查器的问题,但我想不出替代方案。( cannot borrow request_buf as immutable because it is also borrowed as mutable
)。
即使我尝试克隆 request_buf 来解决这个问题,这是非常低效的,temporary value dropped while borrowed
无论我为克隆缓冲区的变量范围有多广,我都会得到一个。
这种模式在 Rust 中根本不可能实现吗?我觉得我已经尝试了所有我能想到的东西,Rust 无时无刻不在和我玩猫捉老鼠。
解决方案
问题是缓冲区必须Request
有一个生命周期。'b
因此调用将对象与缓冲区parse()
相关联,这意味着它现在持有. 这消除了获得与生命一样长的可变借用的可能性。Request
req
request_buf
request_buf
req
这不仅仅是借用检查器的心血来潮:parse()
意味着req
(通常是为了提高效率)保持指向内部的切片的签名request_buf
。可变借用request_buf
将允许您缩小容器或将其增长到超过其当前容量,从而导致它重新分配。任何一种情况都会使所持有的切片无效req
并导致崩溃。
reddit上的评论澄清了解析器不存储解析状态。您应该使用一个足够大的缓冲区,以至于部分解析很少见,如果发生这种情况,您只需从头开始,大概是通过创建一个新Request
缓冲区并为其提供整个缓冲区(后者您已经在做)。例如:
fn parse(mut stream: impl Read) {
let mut request_buf: Vec<u8> = vec![];
let mut buf = [0 as u8; 16384]; // 16k read buffer
let (req, headers) = loop {
match stream.read(&mut buf) {
Ok(size) => request_buf.extend(&buf[0..size]),
Err(_) => {} // handle err,
}
let mut headers = [httparse::EMPTY_HEADER; 16];
let mut req = Request::new(&mut headers);
if req.parse(&request_buf).unwrap().is_complete() {
break (req, headers);
}
};
}
推荐阅读
- docker - 如何将索引从自托管的 Elasticsearch 转换/迁移到 ES docker 容器?
- javascript - P5.js 类未识别
- excel - Excel - 按正则表达式或类似方法拆分字符串
- amazon-web-services - 在存储桶中显示 AWS S3 cli 上传后出现问题
- apache-spark - 使用 Spark / Scala 从数据框中的单个记录创建多个记录?
- google-app-engine - 用户/服务帐户、范围、AppEngine 和 GSuite(工作表 v4 api)
- html - 如何将背景图像设置为仅屏幕的左半部分
- python - 从 Django 视图中的特定论坛类别获取线程
- c - 无法使用 Visual Studio 的 Empty WDM 驱动程序模板中的 NDIS 相关功能
- jenkins - 如何处理詹金斯 http -> https 重定向?