use crate::error::DbResult;
pub trait Codec<T>: Send + Sync {
fn encode_to(&self, value: &T, buf: &mut Vec<u8>);
fn decode_from(&self, bytes: &[u8]) -> DbResult<T>;
}
#[cfg(feature = "rapira-codec")]
#[derive(Default, Clone, Debug)]
pub struct RapiraCodec;
#[cfg(feature = "rapira-codec")]
impl<T: rapira::Rapira> Codec<T> for RapiraCodec {
fn encode_to(&self, value: &T, buf: &mut Vec<u8>) {
buf.clear();
rapira::extend_vec(value, buf);
}
fn decode_from(&self, bytes: &[u8]) -> DbResult<T> {
unsafe {
rapira::deser_unchecked(bytes)
.map_err(|_| crate::error::DbError::CorruptedEntry { offset: 0 })
}
}
}
#[cfg(feature = "bitcode-codec")]
#[derive(Default, Clone, Debug)]
pub struct BitcodeCodec;
#[cfg(feature = "bitcode-codec")]
impl<T: bitcode::Encode + for<'a> bitcode::Decode<'a>> Codec<T> for BitcodeCodec {
fn encode_to(&self, value: &T, buf: &mut Vec<u8>) {
*buf = bitcode::encode(value);
}
fn decode_from(&self, bytes: &[u8]) -> DbResult<T> {
bitcode::decode(bytes).map_err(|_| crate::error::DbError::CorruptedEntry { offset: 0 })
}
}
#[cfg(feature = "postcard-codec")]
#[derive(Default, Clone, Debug)]
pub struct PostcardCodec;
#[cfg(feature = "postcard-codec")]
impl<T: serde::Serialize + for<'a> serde::Deserialize<'a>> Codec<T> for PostcardCodec {
fn encode_to(&self, value: &T, buf: &mut Vec<u8>) {
buf.clear();
*buf = postcard::to_allocvec(value).expect("postcard encode");
}
fn decode_from(&self, bytes: &[u8]) -> DbResult<T> {
postcard::from_bytes(bytes).map_err(|_| crate::error::DbError::CorruptedEntry { offset: 0 })
}
}
#[derive(Default, Clone, Debug)]
pub struct ZerocopyCodec;
impl<T> Codec<T> for ZerocopyCodec
where
T: zerocopy::IntoBytes + zerocopy::FromBytes + zerocopy::Immutable,
{
fn encode_to(&self, value: &T, buf: &mut Vec<u8>) {
buf.clear();
buf.extend_from_slice(zerocopy::IntoBytes::as_bytes(value));
}
fn decode_from(&self, bytes: &[u8]) -> DbResult<T> {
zerocopy::FromBytes::read_from_bytes(bytes)
.map_err(|_| crate::error::DbError::CorruptedEntry { offset: 0 })
}
}
#[cfg(feature = "bytemuck-codec")]
#[derive(Default, Clone, Debug)]
pub struct BytemuckCodec;
#[cfg(feature = "bytemuck-codec")]
impl<T: bytemuck::Pod> Codec<T> for BytemuckCodec {
fn encode_to(&self, value: &T, buf: &mut Vec<u8>) {
buf.clear();
buf.extend_from_slice(bytemuck::bytes_of(value));
}
fn decode_from(&self, bytes: &[u8]) -> DbResult<T> {
bytemuck::try_from_bytes(bytes)
.copied()
.map_err(|_| crate::error::DbError::CorruptedEntry { offset: 0 })
}
}
#[cfg(feature = "bytemuck-codec")]
#[derive(Default, Clone, Debug)]
pub struct BytemuckSliceCodec;
#[cfg(feature = "bytemuck-codec")]
impl<W: BytemuckVec> Codec<W> for BytemuckSliceCodec {
fn encode_to(&self, value: &W, buf: &mut Vec<u8>) {
buf.clear();
buf.extend_from_slice(bytemuck::cast_slice(value.as_slice()));
}
fn decode_from(&self, bytes: &[u8]) -> DbResult<W> {
if !bytes.is_empty() && !bytes.len().is_multiple_of(size_of::<W::Item>()) {
return Err(crate::error::DbError::CorruptedEntry { offset: 0 });
}
Ok(W::from_vec(bytemuck::cast_slice(bytes).to_vec()))
}
}
#[cfg(feature = "bytemuck-codec")]
pub trait BytemuckVec: Send + Sync + Sized {
type Item: bytemuck::Pod;
fn from_vec(v: Vec<Self::Item>) -> Self;
fn as_slice(&self) -> &[Self::Item];
}
#[cfg(feature = "bytemuck-codec")]
impl<T: bytemuck::Pod + Send + Sync> BytemuckVec for Vec<T> {
type Item = T;
fn from_vec(v: Vec<T>) -> Self {
v
}
fn as_slice(&self) -> &[T] {
self
}
}