use std::sync::Arc;
use bytes::Bytes;
use crate::Result;
pub trait CacheCodecImpl: Send + Sync {
fn serialize(&self, writer: &mut dyn std::io::Write) -> Result<()>;
fn deserialize(data: &Bytes) -> Result<Self>
where
Self: Sized;
}
pub(crate) type ArcAny = Arc<dyn std::any::Any + Send + Sync>;
#[derive(Copy, Clone)]
pub struct CacheCodec {
pub(crate) serialize: fn(&ArcAny, &mut dyn std::io::Write) -> Result<()>,
pub(crate) deserialize: fn(&Bytes) -> Result<ArcAny>,
}
impl std::fmt::Debug for CacheCodec {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CacheCodec").finish_non_exhaustive()
}
}
fn serialize_via_impl<T: CacheCodecImpl + 'static>(
any: &ArcAny,
writer: &mut dyn std::io::Write,
) -> Result<()> {
let val = any
.downcast_ref::<T>()
.expect("CacheCodec::serialize called with wrong type (this is a bug in the cache layer)");
val.serialize(writer)
}
fn deserialize_via_impl<T: CacheCodecImpl + 'static>(data: &Bytes) -> Result<ArcAny> {
let val = T::deserialize(data)?;
Ok(Arc::new(val) as ArcAny)
}
impl CacheCodec {
pub fn new(
serialize: fn(&ArcAny, &mut dyn std::io::Write) -> Result<()>,
deserialize: fn(&Bytes) -> Result<ArcAny>,
) -> Self {
Self {
serialize,
deserialize,
}
}
pub fn from_impl<T: CacheCodecImpl + 'static>() -> Self {
Self {
serialize: serialize_via_impl::<T>,
deserialize: deserialize_via_impl::<T>,
}
}
pub fn serialize(&self, value: &ArcAny, writer: &mut dyn std::io::Write) -> Result<()> {
(self.serialize)(value, writer)
}
pub fn deserialize(&self, data: &Bytes) -> Result<ArcAny> {
(self.deserialize)(data)
}
}