#redis #resp #protocols #parser #buffer #serialization #incomplete

kresp

我的简单且易用的Rust包,用于处理REdis序列化协议(RESP)

3个版本

0.1.2 2022年5月2日
0.1.1 2022年4月25日
0.1.0 2022年4月18日

#2466 in 数据库接口

24 每月下载量
kredis 中使用

MIT 许可协议

42KB
1K SLoC

kRESP (Kenneth的RESP解析器)

这是一个小型、流式 RESP (REdis序列化协议) 解析器,注重简洁性和易用性。

我正在开发一个易用的异步Redis客户端库,并构建了这个库作为实现该目标的预步。为了在异步环境中发挥最佳效果,这个库从一开始就被设计为流式处理。可以发送不完整的缓冲区到 RespParser,它将内部保留缓冲区和解析状态,以最小化重解析可能通过网络连接流过的数据。

基本解码

实例化解析器,并给它一些数据!读取方法将返回 Ok(Vec<RespType>),如果解析到结果,将返回结果向量。

let mut parser = RespParser::default();
let simple = "+OK\r\n";

for item in parser.read(simple.as_bytes())? {
    println!("{:#?}", item);
}

返回的类型是 RespType 的变体

let much_more = b"*5\r\n+hello\r\n-woahnow\r\n:-42\r\n$4\r\nhey!\r\n*-1\r\n";
for item in parser.read(much_more)? {
    if let RespType::Array(array) = item {
        for i in array {
            println!("{:#?}", i);
        }
    }
}

允许部分读取,所以不完整的resp块是可以的。输出将为空,直到项完整或达到默认限制512MB。返回的项将不再由解析器拥有。

let some = b"$9\r\n";
assert_eq!(parser.read(some)?.len(), 0);

let the_rest = b"oh, hello\r\n";
println!("{:#?}", parser.read(the_rest)?);

解析器将返回协议违规的错误。当发生错误时,所有内部缓冲区将被清除,以便在不进行额外干预的情况下继续使用解析器。

let bad = b"forgot my type!";
println!("{:#?}", parser.read(bad));

let recovered = b"+all good now though\r\n";
println!("{:#?}", parser.read(recovered)?);

数据编码

此库还支持将 RespType 变体编码到堆分配的字节(Vec<u8>)。

let hello = RespType::BulkString("hello".into());
let world = RespType::BulkString("world!".into());
let array = RespType::array(vec![hello, world]);
let encoded = array.as_bytes();
println!("{:#?}", std::str::from_utf8(&encoded)?);

依赖项

~1–1.5MB
~30K SLoC