Skip to main content

Crate kevy_resp

Crate kevy_resp 

Source
Expand description

kevy-resp — a zero-dependency RESP (REdis Serialization Protocol) codec.

It covers what a client sends to drive commands — the RESP2 multi-bulk request (*N\r\n$len\r\n…) and the inline form (a bare PING\r\n typed over a raw connection) — plus the reply primitives a server writes back. Parsing is incremental and allocation-light: parse_command returns Ok(None) when more bytes are needed, so it composes with a streaming read loop.

Pure Rust, no dependencies. Part of the kevy key–value server.

§Example

use kevy_resp::{encode_bulk, encode_simple_string, parse_command};

// Parse one command from a request buffer.
let (cmd, consumed) = parse_command(b"*2\r\n$4\r\nECHO\r\n$2\r\nhi\r\n")
    .unwrap() // not a protocol error
    .unwrap(); // a complete frame was present
assert_eq!(cmd, vec![b"ECHO".to_vec(), b"hi".to_vec()]);
assert_eq!(consumed, 22);

// A partial frame asks for more bytes rather than erroring.
assert_eq!(parse_command(b"*1\r\n$4\r\nPI").unwrap(), None);

// Encode replies into a caller-owned buffer.
let mut out = Vec::new();
encode_simple_string(&mut out, "PONG");
encode_bulk(&mut out, b"hi");
assert_eq!(out, b"+PONG\r\n$2\r\nhi\r\n");

Structs§

Argv
A parsed command’s argument vector.
ArgvBorrowed
A parsed command’s argument vector that borrows its bytes from a contiguous input buffer.
ArgvIter
Iterator yielding each ArgvView’s arguments as &[u8] slices.
ArgvPool
A recycling pool of owned Argvs. See the module docs for the cross-shard ownership cycle it serves.

Enums§

ProtocolError
Why a buffer could not (yet) be parsed into a command (or reply).
Reply
A parsed RESP reply (server → client) — the client-side counterpart of the crate’s encode_* functions (server-side encoders).
RespVersion
Which version of RESP a connection is speaking. Negotiated via the HELLO command — RESP2 is the default for backwards compatibility with every Redis 6.x and earlier client; RESP3 is opt-in via HELLO 3 and unlocks the additive reply types (Reply::Map / Reply::Set / Reply::Double / Reply::Boolean / Reply::Verbatim / Reply::BigNumber / Reply::Null / Reply::Push / Reply::BlobError) plus out-of-band push frames for PUBLISH delivery.

Traits§

ArgvView
Read-only view over a parsed command’s argument vector.

Functions§

encode_array_len
*<len>\r\n — an array header; follow with len encoded elements.
encode_big_number
(<digits>\r\n — arbitrary-precision integer carried as its string representation. We don’t ship a bignum type (charter: zero deps), so the caller hands in pre-formatted digit bytes.
encode_blob_error
!<len>\r\n<error>\r\n — length-prefixed error. Use when the error payload contains CRLF (the simple -... shape can’t encode it).
encode_boolean
#t\r\n / #f\r\n — boolean.
encode_bulk
$<len>\r\n<data>\r\n
encode_command
Encode a command as a RESP multi-bulk request (client → server): *N\r\n$len\r\n<arg>\r\n…. The inverse of parse_command.
encode_double
,<value>\r\n — a double. inf / -inf / nan are valid wire payloads per spec; we forward Rust’s standard float formatting which emits exactly those tokens.
encode_error
-<s>\r\n
encode_integer
:<n>\r\n
encode_map_header
%<count>\r\n — a map header. Follow with count × 2 sub-replies (key₁ value₁ key₂ value₂ …). The count is the pair count, not the element count.
encode_null
_\r\n — RESP3 true null. RESP2 fallback is the existing crate::encode_null_bulk ($-1\r\n).
encode_null_bulk
$-1\r\n — the RESP2 null bulk string.
encode_push_header
><count>\r\n — an out-of-band push frame header. Follow with count sub-replies. The RESP3 client demultiplexes push frames from regular replies, so this is what PUBLISH / pattern-subscribe delivery uses when the consumer speaks RESP3.
encode_set_header
~<count>\r\n — a set header. Follow with count sub-replies; the receiving client treats them as a set (dedup is its job; the wire doesn’t require it).
encode_simple_string
+<s>\r\n
encode_verbatim
=<len>\r\n<fmt>:<data>\r\n — verbatim string. fmt MUST be a 3-byte format tag (b"txt", b"mkd", b"raw", …); data is the payload after the : separator. The wire len covers the 3-byte fmt + : + payload (so len = 4 + data.len()).
parse_command
Attempt to parse one command from the front of buf.
parse_command_borrowed
Parse one command from the front of buf, recording each arg as a (start, end) range into buf rather than copying its bytes.
parse_command_into
Same as parse_command, but writes into a caller-provided scratch Argv instead of allocating a new one each call. The reactor stores one Argv per shard and reuses it for every cmd on the local hot path; the internal Vec<u8> + Vec<u32> capacities amortise to zero allocations per command after the first few cmds warm them.
parse_reply
Parse one RESP reply from the front of buf. Speaks RESP2 + RESP3.

Type Aliases§

Command
A parsed command: argv, where argv[0] is the command name.