use zerocopy::{FromBytes, Immutable, IntoBytes};
pub trait Blob {
fn to_bytes(&self) -> Vec<u8>;
fn from_bytes(bytes: &[u8]) -> Self;
}
impl Blob for Vec<u8> {
fn to_bytes(&self) -> Vec<u8> {
self.clone()
}
fn from_bytes(bytes: &[u8]) -> Self {
bytes.to_vec()
}
}
impl Blob for Vec<ecow::EcoString> {
fn to_bytes(&self) -> Vec<u8> {
serde_cbor::to_vec(self).expect("Failed to serialize Vec<ecow::EcoString>")
}
fn from_bytes(bytes: &[u8]) -> Self {
serde_cbor::from_slice(bytes).expect("Failed to deserialize Vec<ecow::EcoString>")
}
}
impl Blob for Vec<(f64, f64)> {
fn to_bytes(&self) -> Vec<u8> {
self.iter()
.flat_map(|(a, b)| a.to_le_bytes().into_iter().chain(b.to_le_bytes()))
.collect()
}
fn from_bytes(bytes: &[u8]) -> Self {
assert!(
bytes.len().is_multiple_of(size_of::<f64>() * 2),
"unexpected number of bytes for Vec<(f64, f64)>",
);
bytes
.chunks(size_of::<f64>() * 2)
.map(|v| {
let (a, b) = v.split_at(size_of::<f64>());
(
f64::read_from_bytes(a).expect("invalid number of bytes for type f64"),
f64::read_from_bytes(b).expect("invalid number of bytes for type f64"),
)
})
.collect()
}
}
macro_rules! impl_blob_vec_zerocopy {
($type:ty) => {
impl Blob for Vec<$type>
where
$type: FromBytes + IntoBytes + Immutable,
{
fn to_bytes(&self) -> Vec<u8> {
self.iter()
.flat_map(|item| item.as_bytes())
.copied()
.collect()
}
fn from_bytes(bytes: &[u8]) -> Self {
assert!(
bytes.len().is_multiple_of(size_of::<$type>()),
"unexpected number of bytes for Vec<{}>",
stringify!($type),
);
bytes
.chunks(size_of::<$type>())
.map(|v| <$type>::read_from_bytes(v).expect("invalid chunk size for type T"))
.collect()
}
}
};
}
impl_blob_vec_zerocopy!(i64);
impl_blob_vec_zerocopy!(u128);
impl_blob_vec_zerocopy!(f64);