6个版本 (3个重大更新)
0.4.2 | 2024年7月20日 |
---|---|
0.4.1 | 2024年7月12日 |
0.3.0 | 2024年4月14日 |
0.2.0 | 2024年4月13日 |
0.1.0 | 2024年4月13日 |
#990 in 网络编程
每月535次下载
用于3个包 (2个直接使用)
48KB
1K SLoC
octs
最后,一个优秀的字节操作库。
这个包基于bytes
定义的类型,通过替换其panic的get
和put
函数为可错误的、非panic的read
和write
函数,通过octs::Read
和octs::Write
。
功能
-
基于
bytes
- 提供了用于字节操作的有用类型,并允许通过引用计数廉价地克隆字节分配。非常适合编写零拷贝网络代码。 -
panic函数是错误 - 在网络中,你不能信任你的输入。那么为什么在错误输入上panic是可能的呢?? 在
octs
中,所有可能失败的功能都返回一个Result
。 -
您的类型是一等公民 - 而不是
get_u16
、put_f32
等,只需使用一个read
和write
函数来处理所有类型。这意味着您可以实现Decode
并能够从任何缓冲区中读取它,同样适用于Encode
和write
。 -
专用 varints - 网络原语的基本要素之一在这里实现,无需任何扩展。只需像任何其他值一样
read
或write
一个VarInt
。 -
零不安全 - 我还不够聪明,无法编写不安全代码。
-
#![no_std]
- 就像bytes
一样,但它仍然需要alloc
。
示例
写入
use octs::{Read, Write, VarInt};
fn write_packet(
mut buf: octs::BytesMut,
// ^^^^^^^^^^^^^^
// | re-exports the core `bytes` types
packet_id: u16,
timestamp: u64,
payload: &[u8],
) -> Result<(), octs::BufTooShort> {
// ^^^^^^^^^^^^^^^^^
// | the main error type
buf.write(packet_id)?;
// ^^^^^
// | one `write` function for all your types
buf.write(timestamp)?;
// +---------------^
// | just use ? for errors
// | no panics
buf.write(VarInt(payload.len()))?;
// ^^^^^^^
// | inbuilt support for varints
// | using the Protocol Buffers spec
buf.write_from(payload)?;
// ^^^^^^^^^^
// | copy from an existing buffer
Ok(())
}
读取
use core::num::NonZeroU8;
use octs::{Bytes, BufError, Decode, Read, BufTooShortOr, VarInt};
#[derive(Debug)]
struct Fragment {
num_frags: NonZeroU8,
payload: Bytes,
}
#[derive(Debug)]
enum FragmentError {
InvalidNumFrags,
PayloadTooLarge,
}
impl Decode for Fragment {
// ^^^^^^
// | implement this trait to be able to `read`
// | this value from a buffer
type Error = FragmentError;
fn decode(mut buf: impl Read) -> Result<Self, BufTooShortOr<Self::Error>> {
let num_frags = buf
.read::<NonZeroU8>()
.map_err(|e| e.map_or(|_| FragmentError::InvalidNumFrags))?;
// +--------------^^^^^^^
// | map the `InvalidValue` error of reading
// | a `NonZeroU8` to your own error value
let VarInt(payload_len) = buf
.read::<VarInt<usize>>()
.map_err(|e| e.map_or(|_| FragmentError::PayloadTooLarge))?;
let payload = buf.read_next(payload_len)?;
// +-------------^^^^^^^^^^
// | read the next `payload_len` bytes directly into `Bytes`
// | if `buf` is also a `Bytes`, this is zero-copy!
Ok(Self {
num_frags,
payload
})
}
}
灵感来源
bytes
- 核心字节操作原语,例如可能非连续的bytes::Buf
特性和廉价克隆的bytes::Bytes
类型。octets
- 通用 API 风格,并且将 varints 作为 API 的核心部分safer-bytes
- 使bytes
API 变得更好integer-encoding
- varint 编码/解码的实现
依赖项
~175KB