use crate::{
resp::{
RespDeserializer, Value, ARRAY_TAG, BLOB_ERROR_TAG, ERROR_TAG, PUSH_TAG, SIMPLE_STRING_TAG,
},
Result,
};
use bytes::{BufMut, Bytes, BytesMut};
use serde::Deserialize;
use std::{fmt, ops::Deref};
#[derive(Clone)]
pub struct RespBuf(Bytes);
impl RespBuf {
#[inline]
pub fn new(bytes: Bytes) -> Self {
Self(bytes)
}
pub fn from_chunks(chunks: &Vec<&[u8]>) -> Self {
let mut bytes = BytesMut::new();
bytes.put_u8(ARRAY_TAG);
let mut temp = itoa::Buffer::new();
let str = temp.format(chunks.len());
bytes.put_slice(str.as_bytes());
bytes.put_slice(b"\r\n");
for chunk in chunks {
bytes.put_slice(chunk)
}
Self(bytes.freeze())
}
#[inline]
pub fn from_slice(data: &[u8]) -> RespBuf {
RespBuf(Bytes::copy_from_slice(data))
}
#[inline]
pub fn is_push_message(&self) -> bool {
(!self.0.is_empty() && self.0[0] == PUSH_TAG) || self.is_monitor_message()
}
#[inline]
pub fn is_monitor_message(&self) -> bool {
self.0.len() > 1 && self.0[0] == SIMPLE_STRING_TAG && (self.0[1] as char).is_numeric()
}
#[inline]
pub fn is_error(&self) -> bool {
self.0.len() > 1 && (self.0[0] == ERROR_TAG || self.0[0] == BLOB_ERROR_TAG)
}
#[inline]
pub fn to<'de, T: Deserialize<'de>>(&'de self) -> Result<T> {
let mut deserializer = RespDeserializer::new(&self.0);
T::deserialize(&mut deserializer)
}
#[inline]
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
#[inline]
pub fn ok() -> RespBuf {
RespBuf(Bytes::from_static(b"+OK\r\n"))
}
#[inline]
pub fn nil() -> RespBuf {
RespBuf(Bytes::from_static(b"_\r\n"))
}
}
impl Deref for RespBuf {
type Target = [u8];
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl fmt::Display for RespBuf {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let str = match self.to::<Value>() {
Ok(value) => {
let mut str = format!("{value:?}");
if str.len() > 1000 {
str = str[..1000].to_owned();
}
str
}
Err(e) => format!("RESP buffer error: {e:?}"),
};
f.write_str(&str)
}
}
impl fmt::Debug for RespBuf {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}