use crate::{
Result,
resp::{RespDeserializer, RespFrameParser, RespResponse, RespTapeMut, Value},
};
use bytes::Bytes;
use serde::de::DeserializeOwned;
use std::{fmt, ops::Deref};
#[derive(Clone, Default, PartialEq, Eq, Hash)]
pub(crate) struct RespBuf(Bytes);
impl RespBuf {
#[cfg(any(test, feature = "fuzzing"))]
#[inline]
pub(crate) fn from_slice(data: &[u8]) -> RespBuf {
RespBuf(Bytes::copy_from_slice(data))
}
#[inline]
pub(crate) fn to<T: DeserializeOwned>(&self) -> Result<T> {
let mut tape = RespTapeMut::default();
let (frame, len) = RespFrameParser::new(&self.0, &mut tape).parse()?;
let response = RespResponse::new(RespBuf(self.0.slice(..len)), frame);
T::deserialize(RespDeserializer::new(response.view()?))
}
}
impl Deref for RespBuf {
type Target = Bytes;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
const DISPLAY_MATERIALIZE_LIMIT: usize = 4 * 1024;
impl fmt::Display for RespBuf {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.0.len() > DISPLAY_MATERIALIZE_LIMIT {
return f.write_fmt(format_args!("<RESP buffer of {} bytes>", self.0.len()));
}
match self.to::<Value>() {
Ok(value) => {
let str = format!("{value:?}");
if str.len() > 1000 {
f.write_str(str.get(..1000).unwrap_or("<can't slice to display>"))
} else {
f.write_str(&str)
}
}
Err(e) => f.write_fmt(format_args!("RESP buffer error: {e:?}")),
}
}
}
impl fmt::Debug for RespBuf {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}
impl From<Bytes> for RespBuf {
#[inline(always)]
fn from(value: Bytes) -> Self {
RespBuf(value)
}
}