use std::{
fmt::{Display, Formatter},
sync::Arc,
};
use bytes::Bytes;
#[derive(Debug, Clone)]
pub enum RawData {
String(String),
Bytes(Bytes),
ArcBytes(Arc<Vec<u8>>),
}
impl RawData {
pub fn from_string<T: Into<String>>(value: T) -> RawData {
RawData::String(value.into())
}
pub fn from_arc_bytes(data: Arc<Vec<u8>>) -> Self {
RawData::ArcBytes(data)
}
pub fn from_arc_slice(data: Arc<[u8]>) -> Self {
RawData::ArcBytes(Arc::new(data.as_ref().to_vec()))
}
pub fn as_bytes(&self) -> &[u8] {
match self {
RawData::String(s) => s.as_bytes(),
RawData::Bytes(b) => b.as_ref(),
RawData::ArcBytes(arc) => arc.as_slice(),
}
}
pub fn to_bytes(&self) -> Bytes {
match self {
RawData::String(s) => Bytes::copy_from_slice(s.as_bytes()),
RawData::Bytes(b) => b.clone(),
RawData::ArcBytes(arc) => Bytes::copy_from_slice(arc.as_slice()),
}
}
pub fn into_bytes(self) -> Bytes {
match self {
RawData::String(s) => Bytes::from(s),
RawData::Bytes(b) => b,
RawData::ArcBytes(arc) => match Arc::try_unwrap(arc) {
Ok(vec) => Bytes::from(vec),
Err(shared) => Bytes::copy_from_slice(shared.as_slice()),
},
}
}
pub fn is_zero_copy(&self) -> bool {
matches!(self, RawData::ArcBytes(_))
}
pub fn len(&self) -> usize {
self.as_bytes().len()
}
pub fn is_empty(&self) -> bool {
match self {
RawData::String(value) => value.is_empty(),
RawData::Bytes(value) => value.is_empty(),
RawData::ArcBytes(arc) => arc.is_empty(),
}
}
}
impl Display for RawData {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
RawData::String(value) => f.write_str(value),
RawData::Bytes(value) => f.write_str(&String::from_utf8_lossy(value)),
RawData::ArcBytes(arc) => f.write_str(&String::from_utf8_lossy(arc.as_slice())),
}
}
}