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;
39pub mod ops_table;
40mod argv_borrowed;
41mod argv_pool;
42mod argv_view;
43mod error;
44mod inline_ranges;
45mod reply_encode;
46mod reply_encode_resp3;
47mod reply_parse;
48mod request;
49mod request_borrowed;
50pub mod fuzz;
51
52pub use argv::{Argv, Command};
53pub use argv_borrowed::ArgvBorrowed;
54pub use argv_pool::ArgvPool;
55pub use argv_view::{ArgvIter, ArgvView};
56pub use error::ProtocolError;
57pub use reply_encode::{
58    encode_array_len, encode_bulk, encode_command, encode_command_borrowed, encode_error,
59    encode_integer, encode_null_bulk, encode_simple_string,
60};
61pub use reply_encode_resp3::{
62    encode_big_number, encode_blob_error, encode_boolean, encode_double, encode_map_header,
63    encode_null, encode_push_header, encode_set_header, encode_verbatim,
64};
65pub use reply_parse::{Reply, parse_reply};
66pub use request::{parse_command, parse_command_into};
67pub use request_borrowed::parse_command_borrowed;
68
69/// Which version of RESP a connection is speaking. Negotiated via the
70/// `HELLO` command — RESP2 is the default for backwards compatibility
71/// with every Redis 6.x and earlier client; RESP3 is opt-in via
72/// `HELLO 3` and unlocks the additive reply types
73/// ([`Reply::Map`] / [`Reply::Set`] / [`Reply::Double`] / [`Reply::Boolean`]
74/// / [`Reply::Verbatim`] / [`Reply::BigNumber`] / [`Reply::Null`] /
75/// [`Reply::Push`] / [`Reply::BlobError`]) plus out-of-band push frames
76/// for `PUBLISH` delivery.
77///
78/// Stored per-connection in `kevy-rt` and forwarded to dispatch so each
79/// reply encoder can pick the right wire shape — see the kevy v2 RESP3
80/// design notes for the full phase plan.
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
82pub enum RespVersion {
83    /// RESP2 — every reply is one of the seven legacy prefixes
84    /// (`+ - : $ * $-1 *-1`). Default for backward compatibility.
85    #[default]
86    V2,
87    /// RESP3 — adds 9 reply prefixes (`% ~ , # = ( _ > !`) plus
88    /// attributes (`|`). Opt-in via `HELLO 3`.
89    V3,
90}