resp-rs
Zero-copy RESP2 and RESP3 protocol parser and serializer for Rust.
A high-performance Rust library for parsing and serializing the Redis Serialization Protocol (RESP), supporting both RESP2 and RESP3.
Features
- Zero-copy parsing -- uses
bytes::Bytesto slice into the input buffer without copying - RESP2 and RESP3 -- full support for both protocol versions with separate frame types
- Streaming parser -- handles partial reads and pipelining for incremental TCP data
- Serialization -- convert frames back to wire format with
frame_to_bytes - Tokio codec -- optional
Decoder/Encoderfor async TCP viatokio_util::codec::Framed - Frame accessors --
as_str(),as_integer(),into_array(),is_null(), and more - Cluster support -- optional CRC16 hash slot calculation with hash tag extraction
- High performance -- up to 2-9x faster than
redis-protocol(see benchmarks) no_stdcompatible -- works in embedded/WASM with justalloc- Minimal dependencies -- only
bytesandthiserror(bothno_std-ready)
Usage
Add to your Cargo.toml:
[]
= "0.1"
Parse a RESP3 frame
use Bytes;
use resp3;
let data = from;
let = parse_frame.unwrap;
assert_eq!;
assert!;
Parse a RESP2 frame
use Bytes;
use resp2;
let data = from;
let = parse_frame.unwrap;
// frame is Array([BulkString("SET"), BulkString("key"), BulkString("value")])
Serialize a frame
use Bytes;
use ;
let frame = Array;
let wire = frame_to_bytes;
assert_eq!;
Streaming parser (incremental TCP reads)
use Bytes;
use Parser;
let mut parser = new;
// Feed partial data
parser.feed;
assert!; // incomplete
// Feed the rest
parser.feed;
let frame = parser.next_frame.unwrap.unwrap; // complete!
RESP3 types
RESP3 adds several types beyond RESP2:
use Bytes;
use ;
// Null
let = parse_frame.unwrap;
assert_eq!;
// Boolean
let = parse_frame.unwrap;
assert_eq!;
// Double
let = parse_frame.unwrap;
assert_eq!;
// Map
let data = from;
let = parse_frame.unwrap;
// frame is Map([(SimpleString("key1"), Integer(1)), (SimpleString("key2"), Integer(2))])
Supported RESP3 types
| Type | Tag | Example |
|---|---|---|
| Simple String | + |
+OK\r\n |
| Simple Error | - |
-ERR msg\r\n |
| Integer | : |
:42\r\n |
| Bulk String | $ |
$5\r\nhello\r\n |
| Null | _ |
_\r\n |
| Boolean | # |
#t\r\n |
| Double | , |
,3.14\r\n |
| Big Number | ( |
(123456\r\n |
| Blob Error | ! |
!5\r\nERROR\r\n |
| Verbatim String | = |
=15\r\ntxt:hello world\r\n |
| Array | * |
*2\r\n:1\r\n:2\r\n |
| Map | % |
%1\r\n+k\r\n+v\r\n |
| Set | ~ |
~2\r\n:1\r\n:2\r\n |
| Attribute | | |
|1\r\n+k\r\n+v\r\n |
| Push | > |
>2\r\n+msg\r\n:1\r\n |
Streaming variants (chunked strings, arrays, maps, sets, attributes, pushes) are also fully supported.
Optional Features
| Feature | Description | Dependencies |
|---|---|---|
std (default) |
Standard library support | -- |
codec |
Tokio Decoder/Encoder for async TCP |
tokio, tokio-util |
cluster |
CRC16 hash slot calculation | -- |
unsafe-internals |
Unchecked parser for pre-validated data | -- |
# Async Redis client
= { = "0.1", = ["codec"] }
# Embedded / WASM
= { = "0.1", = false }
# Everything
= { = "0.1", = ["codec", "cluster", "unsafe-internals"] }
Examples
Async ping (Tokio codec)
Connect to Redis and send a PING using the async codec:
Parse demo
A standalone demo of RESP2/RESP3 parsing, serialization, and the streaming parser:
Breadis
A bread-themed Redis-compatible TCP server that speaks RESP2 -- demonstrates real-world usage with the streaming parser for incremental TCP reads.
# In another terminal:
Benchmarks
Comparative benchmarks against redis-protocol v6
(run with cargo bench --bench comparison):
| Benchmark | resp-rs | redis-protocol | Speedup |
|---|---|---|---|
| resp2/simple_string | 12.6 ns | 20.8 ns | 1.7x |
| resp2/bulk_string | 12.9 ns | 26.4 ns | 2.0x |
| resp2/array (SET cmd) | 43.7 ns | 124.9 ns | 2.9x |
| resp2/array (100 elems) | 828 ns | 3.08 us | 3.7x |
| resp3/simple_string | 39.1 ns | 81.0 ns | 2.1x |
| resp3/bulk_string | 41.5 ns | 90.8 ns | 2.2x |
| resp3/array (SET cmd) | 83.9 ns | 366.8 ns | 4.4x |
| resp3/integer (i64 max) | 48.1 ns | 94.3 ns | 2.0x |
| resp3/array (100 elems) | 1.13 us | 9.76 us | 8.6x |
Run the full benchmark suite:
Minimum Supported Rust Version
The MSRV is 1.85 (Rust 2024 edition).
License
Licensed under either of
at your option.
Contributing
Contributions are welcome. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.