use bytes::Bytes;
#[derive(Clone, Debug, Default)]
pub struct MessageBody {
raw: Option<Bytes>,
compressed: Option<Bytes>,
}
impl MessageBody {
#[inline]
pub fn new(data: impl Into<Bytes>) -> Self {
Self {
raw: Some(data.into()),
compressed: None,
}
}
#[inline]
pub const fn empty() -> Self {
Self {
raw: None,
compressed: None,
}
}
#[inline]
pub fn from_compressed(raw: Bytes, compressed: Bytes) -> Self {
Self {
raw: Some(raw),
compressed: Some(compressed),
}
}
#[inline]
pub fn as_slice(&self) -> &[u8] {
self.raw.as_ref().map(|b| &b[..]).unwrap_or(&[])
}
#[inline]
pub fn raw(&self) -> Option<&Bytes> {
self.raw.as_ref()
}
#[inline]
pub fn raw_mut(&mut self) -> &mut Option<Bytes> {
&mut self.raw
}
#[inline]
pub fn compressed(&self) -> Option<&Bytes> {
self.compressed.as_ref()
}
#[inline]
pub fn compressed_mut(&mut self) -> &mut Option<Bytes> {
&mut self.compressed
}
#[inline]
pub(crate) fn set_compressed(&mut self, compressed: Bytes) {
self.compressed = Some(compressed);
}
#[inline]
pub fn is_compressed(&self) -> bool {
self.compressed.is_some()
}
#[inline]
pub fn into_bytes(self) -> Bytes {
self.raw.unwrap_or_default()
}
#[inline]
pub fn len(&self) -> usize {
self.raw.as_ref().map_or(0, |b| b.len())
}
#[inline]
pub fn is_empty(&self) -> bool {
let raw_empty = self.raw.as_ref().is_none_or(|b| b.is_empty());
let compressed_empty = self.compressed.as_ref().is_none_or(|b| b.is_empty());
raw_empty && compressed_empty
}
}
impl AsRef<[u8]> for MessageBody {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl From<Vec<u8>> for MessageBody {
fn from(data: Vec<u8>) -> Self {
Self::new(data)
}
}
impl From<Bytes> for MessageBody {
fn from(data: Bytes) -> Self {
Self::new(data)
}
}
impl From<&[u8]> for MessageBody {
fn from(data: &[u8]) -> Self {
Self::new(Bytes::copy_from_slice(data))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn raw_body_exposes_uncompressed_bytes() {
let raw = Bytes::from_static(b"message body");
let body = MessageBody::new(raw.clone());
assert_eq!(body.as_slice(), raw.as_ref());
assert!(!body.is_empty());
assert!(!body.is_compressed());
assert_eq!(body.compressed(), None);
assert_eq!(body.into_bytes(), raw);
}
#[test]
fn compressed_body_keeps_independent_buffers() {
let raw = Bytes::from_static(b"message body");
let compressed = Bytes::from_static(b"compressed");
let mut body = MessageBody::from_compressed(raw.clone(), compressed.clone());
assert_eq!(body.raw(), Some(&raw));
assert_eq!(body.compressed(), Some(&compressed));
assert_eq!(body.len(), raw.len());
assert!(body.is_compressed());
*body.raw_mut() = Some(Bytes::new());
assert_eq!(body.compressed(), Some(&compressed));
assert!(!body.is_empty());
*body.compressed_mut() = None;
assert_eq!(body.raw(), Some(&Bytes::new()));
assert!(body.is_empty());
assert!(MessageBody::empty().is_empty());
}
}