1 个不稳定版本
0.1.0 | 2023年2月20日 |
---|
#2013 在 解析器实现
270KB
670 行
buffed
,一个用于 Rust 的增强缓冲读取器。
buffed
提供类似于 std::io::BufRead
的特性和实现。 buffed
的特性和结构允许直接从字节流中读取序列化数据。它不需要输入中的任何结构,同时利用缓冲机制。它还使得避免复制和分配变得容易。
注意:这个包主要是作为一个个人挑战制作的。它尚未经过适当的测试或审计,你不应该用它做任何事情比爱好更严肃的事情。考虑使用 sequoia-pgp 的 buffered-reader。我们仍然乐意接受问题和合并拉取请求!我们仍然希望这个包成为一个很好的抽象。
问题的根本
这个包最初是为了解决以下问题而设计的:读取一个用户提供的,UTF8 编码的文本文件,并通过它读取一些数据。以 闪电般快速tm 的速度执行,永远不占用内存,同时还能对恶意输入具有鲁棒性。
对速度的要求意味着要使用缓冲,这已经限制了我们可以使用的标准库中的内容
std::io::Read::read_to_string
将整个文件加载到内存中,这显然不符合第二个和最后一个要求。std::io::BufRead::read_line
实际上在防御恶意输入时也有同样的问题:没有换行符的大文件将被整个加载到内存中。
标准库也不允许使用合理的高级API来控制分配(我们也不期望它这样做),这可能会使事物更快。
buffed
的API
buffed
提供了一些特性
BuffedRead
,类似于std::io::BufRead
,但在缓冲和允许读取实现FromBytes
的类型方面提供了更多控制,无需复制。FromBytes
(以及相关的FromBytesError
),封装了读取数据的解析(和错误报告)逻辑。计划是为此特性实现大多数你可能需要的类型,如nom
的解析器输出、serde 可序列化类型等。如果你希望为某些内容实现它,请提交问题/PR!只要它是在非默认的可选功能之后,合并它应该很容易。
Buffer
,是BuffedReader
缓冲区的特性。它可以被其他BuffedRead
实现使用,以利用比BuffedReader
使用的技术更先进的缓冲技术。
还有一些类型
BuffedReader
,对于BuffedRead
,就像BufReader
对于BufRead
。这是一个默认实现,包装了另一个实现std::io::Read
的类型。值得注意的是,它使用了一个BoxBuffer
,可以根据需要替换为另一个Buffer
的实现。BoxBuffer
,基于简单的Box
字节切片的“默认”实现(Box<[u8]>
)。Error
,是BuffedRead
使用的通用错误类型。
示例
使用 Buffedread
API 读取文件的全部内容可能如下所示
use std::fs::File;
use buffed::{BuffedRead, BuffedReader, FromBytes};
fn main() {
let file = File::open("tests/assets/capital-ru.txt").unwrap();
let mut r = BuffedReader::new(file);
loop {
match r.fill_buf() {
// EOF
Ok("") => { return; }
Ok(data) => {
let size = data.size();
// Do something with data
// ...
r.consume(size).unwrap();
},
// Oopsies
Err(err) => panic!("{err}"),
}
}
}
或者,BuffedRead
的 require_fill_buf(amount: usize)
方法接受一个最小数据量,当达到(除非 EOF)时返回,而 require_fill_buf_no_alloc(amount: usize)
做同样的操作,但如果缓冲区需要重新分配以容纳数据量,则出错。
替代方案
如果你在寻找类似 buffed
的东西,你可能对以下内容感兴趣
- buffered-reader:为 sequoia-pgp 项目提供的缓冲读取器实现。它完成了我们想要的所有事情,包括使用其堆叠读取器的概念解析对象的方式。它也是一个经过更多实战测试和更健壮的实现!如果你打算将
buffed
用于比业余爱好更严肃的事情,你应该考虑使用这个替代方案。 - 使用类似 serde 或 nom 的crate使用
std::io
类型实现定制的解决方案。这并不是最容易的道路,但如果其他方法不适合你的情况,这可能是最好的选择。
以下内容也可能有价值,尽管我们不会考虑使用它们,原因如下:
- io-enum:与
buffed
实现相同,但不需要扩展std
的特质,仅适用于枚举。 - buf_redux:替代了
std::io
的缓冲类型,但仍仅读取字节,这使得在不复制的情况下处理UTF8变得困难且笨拙。自2019年8月以来没有发布新版本。 - text_io:基于宏的无缓冲方法。我们发现它过于脆弱,并且一年内没有多少活动。
- ciborium-io:为
#![no_std]
提供了简单的Read
和Write
特质。大部分功能不完整,自2021年12月以来没有活动。 - layered-io:在类似
buffed
的思想下扩展了std
的Read
和Write
特质,但没有增加太多。