use std::error::Error as StdError;
use std::fmt;
pub trait Codec<T> {
fn encode(&self, value: &T) -> Result<Vec<u8>, CodecError>;
fn decode(&self, bytes: &[u8]) -> Result<T, CodecError>;
}
#[derive(Debug)]
pub struct CodecError(String);
impl CodecError {
pub fn new(error: impl fmt::Display) -> Self {
Self(error.to_string())
}
}
impl fmt::Display for CodecError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "codec error: {}", self.0)
}
}
impl StdError for CodecError {}
#[cfg(feature = "serde")]
#[derive(Clone, Copy, Debug, Default)]
pub struct Bincode;
#[cfg(feature = "serde")]
impl<T> Codec<T> for Bincode
where
T: serde::Serialize + serde::de::DeserializeOwned,
{
fn encode(&self, value: &T) -> Result<Vec<u8>, CodecError> {
bincode::serialize(value).map_err(CodecError::new)
}
fn decode(&self, bytes: &[u8]) -> Result<T, CodecError> {
bincode::deserialize(bytes).map_err(CodecError::new)
}
}
#[cfg(feature = "rkyv")]
#[derive(Clone, Copy, Debug, Default)]
pub struct Rkyv;
#[cfg(feature = "rkyv")]
impl<T> Codec<T> for Rkyv
where
T: rkyv::Archive
+ for<'a> rkyv::Serialize<
rkyv::rancor::Strategy<
rkyv::ser::Serializer<
rkyv::util::AlignedVec,
rkyv::ser::allocator::ArenaHandle<'a>,
rkyv::ser::sharing::Share,
>,
rkyv::rancor::Error,
>,
>,
T::Archived: for<'a> rkyv::bytecheck::CheckBytes<rkyv::api::high::HighValidator<'a, rkyv::rancor::Error>>
+ rkyv::Deserialize<T, rkyv::api::high::HighDeserializer<rkyv::rancor::Error>>,
{
fn encode(&self, value: &T) -> Result<Vec<u8>, CodecError> {
rkyv::to_bytes::<rkyv::rancor::Error>(value)
.map(|bytes| bytes.to_vec())
.map_err(CodecError::new)
}
fn decode(&self, bytes: &[u8]) -> Result<T, CodecError> {
let mut aligned = rkyv::util::AlignedVec::<16>::new();
aligned.extend_from_slice(bytes);
rkyv::from_bytes::<T, rkyv::rancor::Error>(&aligned).map_err(CodecError::new)
}
}