Skip to main content

kevy_resp/
lib.rs

1//! kevy-resp — a zero-dependency [RESP] (REdis Serialization Protocol) codec.
2//!
3//! It covers what a client sends to drive commands — the RESP2 multi-bulk
4//! request (`*N\r\n$len\r\n…`) and the inline form (a bare `PING\r\n` typed over
5//! a raw connection) — plus the reply primitives a server writes back. Parsing
6//! is incremental and allocation-light: [`parse_command`] returns `Ok(None)`
7//! when more bytes are needed, so it composes with a streaming read loop.
8//!
9//! Pure Rust, no dependencies. Part of the [kevy] key–value server.
10//!
11//! [RESP]: https://redis.io/docs/latest/develop/reference/protocol-spec/
12//! [kevy]: https://crates.io/crates/kevy
13//!
14//! # Example
15//!
16//! ```
17//! use kevy_resp::{encode_bulk, encode_simple_string, parse_command};
18//!
19//! // Parse one command from a request buffer.
20//! let (cmd, consumed) = parse_command(b"*2\r\n$4\r\nECHO\r\n$2\r\nhi\r\n")
21//!     .unwrap() // not a protocol error
22//!     .unwrap(); // a complete frame was present
23//! assert_eq!(cmd, vec![b"ECHO".to_vec(), b"hi".to_vec()]);
24//! assert_eq!(consumed, 22);
25//!
26//! // A partial frame asks for more bytes rather than erroring.
27//! assert_eq!(parse_command(b"*1\r\n$4\r\nPI").unwrap(), None);
28//!
29//! // Encode replies into a caller-owned buffer.
30//! let mut out = Vec::new();
31//! encode_simple_string(&mut out, "PONG");
32//! encode_bulk(&mut out, b"hi");
33//! assert_eq!(out, b"+PONG\r\n$2\r\nhi\r\n");
34//! ```
35#![forbid(unsafe_code)]
36#![warn(missing_docs)]
37
38mod argv;
39mod argv_borrowed;
40mod argv_pool;
41mod argv_view;
42mod error;
43mod inline_ranges;
44mod reply_encode;
45mod reply_encode_resp3;
46mod reply_parse;
47mod request;
48mod request_borrowed;
49pub mod fuzz;
50
51pub use argv::{Argv, Command};
52pub use argv_borrowed::ArgvBorrowed;
53pub use argv_pool::ArgvPool;
54pub use argv_view::{ArgvIter, ArgvView};
55pub use error::ProtocolError;
56pub use reply_encode::{
57    encode_array_len, encode_bulk, encode_command, encode_command_borrowed, encode_error,
58    encode_integer, encode_null_bulk, encode_simple_string,
59};
60pub use reply_encode_resp3::{
61    encode_big_number, encode_blob_error, encode_boolean, encode_double, encode_map_header,
62    encode_null, encode_push_header, encode_set_header, encode_verbatim,
63};
64pub use reply_parse::{Reply, parse_reply};
65pub use request::{parse_command, parse_command_into};
66pub use request_borrowed::parse_command_borrowed;
67
68/// Which version of RESP a connection is speaking. Negotiated via the
69/// `HELLO` command — RESP2 is the default for backwards compatibility
70/// with every Redis 6.x and earlier client; RESP3 is opt-in via
71/// `HELLO 3` and unlocks the additive reply types
72/// ([`Reply::Map`] / [`Reply::Set`] / [`Reply::Double`] / [`Reply::Boolean`]
73/// / [`Reply::Verbatim`] / [`Reply::BigNumber`] / [`Reply::Null`] /
74/// [`Reply::Push`] / [`Reply::BlobError`]) plus out-of-band push frames
75/// for `PUBLISH` delivery.
76///
77/// Stored per-connection in `kevy-rt` and forwarded to dispatch so each
78/// reply encoder can pick the right wire shape — see the kevy v2 RESP3
79/// design notes for the full phase plan.
80#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
81pub enum RespVersion {
82    /// RESP2 — every reply is one of the seven legacy prefixes
83    /// (`+ - : $ * $-1 *-1`). Default for backward compatibility.
84    #[default]
85    V2,
86    /// RESP3 — adds 9 reply prefixes (`% ~ , # = ( _ > !`) plus
87    /// attributes (`|`). Opt-in via `HELLO 3`.
88    V3,
89}