#[derive(Debug, Clone, PartialEq)]
pub enum Resp {
Bulk(Vec<u8>),
Simple(String),
Int(i64),
Null,
Array(Vec<Resp>),
Map(Vec<(Resp, Resp)>),
Push(Vec<Resp>),
Verbatim(String),
}
impl Resp {
pub fn bulk(s: impl AsRef<[u8]>) -> Resp {
Resp::Bulk(s.as_ref().to_vec())
}
pub fn encode(&self, proto: u8) -> Vec<u8> {
let mut out = Vec::new();
self.encode_into(proto, &mut out);
out
}
fn encode_into(&self, proto: u8, out: &mut Vec<u8>) {
use super::actions::{encode_bulk_string, encode_integer, encode_simple_string};
match self {
Resp::Bulk(b) => out.extend_from_slice(&encode_bulk_string(b)),
Resp::Simple(s) => out.extend_from_slice(&encode_simple_string(s)),
Resp::Int(i) => out.extend_from_slice(&encode_integer(*i)),
Resp::Null => out.extend_from_slice(&super::resp3::null(proto)),
Resp::Array(items) => {
out.extend_from_slice(format!("*{}\r\n", items.len()).as_bytes());
for item in items {
item.encode_into(proto, out);
}
}
Resp::Push(items) => {
let marker = if proto == 3 { '>' } else { '*' };
out.extend_from_slice(format!("{marker}{}\r\n", items.len()).as_bytes());
for item in items {
item.encode_into(proto, out);
}
}
Resp::Map(entries) => {
if proto == 3 {
out.extend_from_slice(format!("%{}\r\n", entries.len()).as_bytes());
} else {
out.extend_from_slice(format!("*{}\r\n", entries.len() * 2).as_bytes());
}
for (k, v) in entries {
k.encode_into(proto, out);
v.encode_into(proto, out);
}
}
Resp::Verbatim(text) => {
if proto == 3 {
let body = format!("txt:{text}");
out.extend_from_slice(format!("={}\r\n", body.len()).as_bytes());
out.extend_from_slice(body.as_bytes());
out.extend_from_slice(b"\r\n");
} else {
out.extend_from_slice(&encode_bulk_string(text.as_bytes()));
}
}
}
}
}