#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RespCommand {
args: Vec<Vec<u8>>,
}
impl RespCommand {
pub(crate) fn new(args: Vec<Vec<u8>>) -> Self {
Self { args }
}
pub fn args(&self) -> &[Vec<u8>] {
&self.args
}
pub fn into_args(self) -> Vec<Vec<u8>> {
self.args
}
pub fn to_resp3_bytes(&self) -> Vec<u8> {
let mut buf = Vec::new();
buf.extend_from_slice(format!("*{}\r\n", self.args.len()).as_bytes());
for arg in &self.args {
buf.extend_from_slice(format!("${}\r\n", arg.len()).as_bytes());
buf.extend_from_slice(arg);
buf.extend_from_slice(b"\r\n");
}
buf
}
}
#[cfg(test)]
mod tests {
use super::*;
use rstest::*;
#[rstest]
fn test_resp3_bytes_set() {
let cmd = RespCommand::new(vec![
b"SET".to_vec(),
b"mykey".to_vec(),
b"myvalue".to_vec(),
]);
let bytes = cmd.to_resp3_bytes();
assert_eq!(
bytes,
b"*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n"
);
}
#[rstest]
fn test_args_returns_slice() {
let cmd = RespCommand::new(vec![b"PING".to_vec()]);
assert_eq!(cmd.args(), &[b"PING".to_vec()]);
}
#[rstest]
fn test_into_args_consumes() {
let cmd = RespCommand::new(vec![b"GET".to_vec(), b"k".to_vec()]);
let args = cmd.into_args();
assert_eq!(args, vec![b"GET".to_vec(), b"k".to_vec()]);
}
#[rstest]
fn test_resp3_bytes_single_arg() {
let cmd = RespCommand::new(vec![b"PING".to_vec()]);
let bytes = cmd.to_resp3_bytes();
assert_eq!(bytes, b"*1\r\n$4\r\nPING\r\n");
}
}