15 个不稳定版本 (4 个破坏性更新)
0.5.0 | 2022年3月21日 |
---|---|
0.4.0 | 2022年3月21日 |
0.3.1 | 2021年12月30日 |
0.3.0 | 2021年10月9日 |
0.1.3 | 2020年10月30日 |
#449 in 解析器实现
每月8,273次下载
用于 7 个crate (6 个直接)
48KB
394 行
fixed-buffer
这是一个 Rust 库,具有固定大小的缓冲区,适用于网络协议解析器和文件解析器。
特性
禁止(不安全代码)
- 仅依赖
std
- 将字节写入缓冲区并读取它们
- 位于栈上
- 不分配
- 使用它读取流,搜索分隔符,并将剩余字节保存用于下一次读取。
- 无宏
- 良好的测试覆盖率(99%)
- 通过启用 cargo 功能
async-std-feature
,futures-io
,smol-feature
或tokio
支持异步。
限制
- 不是一个循环缓冲区。您可以定期调用
shift()
将未读取的字节移动到缓冲区的开头。
示例
读取并处理来自远程客户端的请求
use fixed_buffer::{deframe_line, FixedBuf};
use std::io::Error;
use std::net::TcpStream;
fn handle_conn(mut tcp_stream: TcpStream) -> Result<(), Error> {
let mut buf: FixedBuf<4096> = FixedBuf::new();
loop {
// Read a line
// and leave leftover bytes in `buf`.
let line_bytes = match buf.read_frame(
&mut tcp_stream, deframe_line)? {
Some(line_bytes) => line_bytes,
None => return Ok(()),
};
let request = Request::parse(line_bytes)?;
handle_request(request)?;
}
}
完整的示例,请参阅 tests/server.rs
.
读取并处理记录
use fixed_buffer::FixedBuf;
use std::io::{Error, ErrorKind, Read};
use std::net::TcpStream;
fn try_process_record(b: &[u8]) -> Result<usize, Error> {
if b.len() < 2 {
return Ok(0);
}
if b.starts_with("ab".as_bytes()) {
println!("found record");
Ok(2)
} else {
Err(Error::new(ErrorKind::InvalidData, "bad record"))
}
}
fn read_and_process<R: Read>(mut input: R) -> Result<(), Error> {
let mut buf: FixedBuf<1024> = FixedBuf::new();
loop {
// Read a chunk into the buffer.
if buf.copy_once_from(&mut input)? == 0 {
return if buf.len() == 0 {
// EOF at record boundary
Ok(())
} else {
// EOF in the middle of a record
Err(Error::from(
ErrorKind::UnexpectedEof))
};
}
// Process records in the buffer.
loop {
let num_to_consume =
try_process_record(buf.readable())?;
if num_to_consume == 0 {
break;
}
buf.try_read_exact(num_to_consume).unwrap();
}
// Shift data in the buffer to free up
// space at the end for writing.
buf.shift();
}
}
#
From<[u8; SIZE]>
的实现对测试很有用。示例
use core::convert::From;
assert_eq!(3, FixedBuf::from(*b"abc").len());
替代方案
bytes
buf_redux
,支持循环缓冲区std::io::BufReader
std::io::BufWriter
static-buffer
,于2016年更新block-buffer
,用于处理固定长度的数据块arrayvec
,具有固定容量的向量。
变更日志
- v0.5.0 - 将
ReadWriteChain
和ReadWriteTake
移动到新的read-write-ext
包。 - v0.4.0
从<&[u8]>
- 将
write_bytes
修改为AsRef<[u8]>
- 将
try_read_exact
修改为read_and_copy_exact
。 - 将
try_read_bytes
修改为try_read_exact
。 - 移除
empty
、filled
、read_byte
、read_bytes
、try_parse
和write_str
。 deframe
允许在不返回框架的情况下消耗字节write_bytes
尽可能写入字节,并在无法写入任何字节时返回新的NoWritableSpace
错误。移除NotEnoughSpaceError
。现在该方法的行为类似于std::io::Write::write
。
- v0.3.1 - 实现
From<NotEnoughSpaceError>
和From<MalformedInputError>
对String
。
更早的变更日志条目
- v0.3.0 - 破坏性 API 变更
- 将类型参数更改为常量缓冲区大小。例如:
FixedBuf<1024>
。 - 移除
new
参数。 - 移除
capacity
。 - 移除
Copy
实现。 - 将
writable
返回类型更改为&mut [u8]
。
- 将类型参数更改为常量缓冲区大小。例如:
- v0.2.3
- v0.2.2 - 在 README 中添加徽章
- v0.2.1 - 添加
deframe
和mem
,这是AsyncFixedBuf::read_frame
所必需的。 - v0.2.0
- 将 tokio 支持移动到
fixed_buffer_tokio
。 - 添加
copy_once_from
、read_block
、ReadWriteChain
和ReadWriteTake
。
- 将 tokio 支持移动到
- v0.1.7 - 添加
FixedBuf::escape_ascii
。 - v0.1.6 - 添加
filled
构造函数。 - v0.1.5 - 将
read_delimited
修改为返回Option<&[u8]>
,以实现干净的 EOF 处理。 - v0.1.4 - 添加
clear()
。 - v0.1.3
- 感谢 freax13 对这些更改
- 支持任何缓冲区大小。现在您可以使用
FixedBuf<[u8; 42]>
- 支持任何
AsRef<[u8]> + AsMut<[u8]>
内部内存值[u8;N]
Box<[u8; N]>
&mut [u8]
Vec<u8>
- 支持任何缓冲区大小。现在您可以使用
- 将
new_with_mem
重命名为new
。使用FixedBuf::default()
来构造任何FixedBuf<T: Default>
,这包括 大小最多为 32 的数组。
- 感谢 freax13 对这些更改
- v0.1.2 - 更新文档。
- v0.1.1 - 首次发布版本
待办事项
- 更改文档中的链接到标准样式。不要链接到
docs.rs
。 - 想法:
buf.slice(buf.read_frame(&mut reader, deframe_crlf))
- 添加一个
frame_copy_iter
函数。由于借用规则,此函数必须返回非借用(分配和复制)数据。 - 在
- DONE - Linux x86 64 位
- macOS
- Windows
- https://crate-ci.github.io/pr/testing.html#travisci
- Linux ARM 64 位(树莓派 3 及更高版本)
- Linux ARM 32 位(树莓派 2)
- RISCV & ESP32 固件?
- DONE - 尝试使此crate符合 Rust API 指南。
- 完成 - 了解如何在crate文档中包含Readme.md信息。
- 完成 - 将仓库设置为公开
- 完成 - 设置持续集成测试和横幅。
- 完成 - 添加一些文档测试
- 完成 - 在Gitlab.com上设置公开仓库
- 完成 - 发布到crates.io
- 完成 - 阅读以下内容 https://crate-ci.github.io/index.html
- 完成 - 从经验丰富的rustacean那里获得代码审查
- 完成 - 添加和更新变更日志
发布流程
- 编辑
Cargo.toml
并提升版本号。 - 运行
../release.sh
许可证:Apache-2.0
依赖项
~0–1.2MB
~19K SLoC