use bytes::Bytes;
use serde::{de::DeserializeOwned, Serialize};
use crate::{CacheError, Result};
pub trait CacheCodec: Clone + Send + Sync + 'static {
fn encode<T>(&self, value: &T) -> Result<Bytes>
where
T: Serialize;
fn decode<T>(&self, bytes: &Bytes) -> Result<T>
where
T: DeserializeOwned;
}
#[derive(Debug, Clone, Copy, Default)]
pub struct PostcardCodec;
impl CacheCodec for PostcardCodec {
fn encode<T>(&self, value: &T) -> Result<Bytes>
where
T: Serialize,
{
postcard::to_allocvec(value)
.map(Bytes::from)
.map_err(|source| CacheError::Encode(source.to_string()))
}
fn decode<T>(&self, bytes: &Bytes) -> Result<T>
where
T: DeserializeOwned,
{
postcard::from_bytes(bytes).map_err(|source| CacheError::Decode(source.to_string()))
}
}
#[cfg(test)]
mod tests {
use serde::ser::{Serialize, Serializer};
use super::*;
struct FailingSerialize;
impl Serialize for FailingSerialize {
fn serialize<S>(&self, _serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
Err(serde::ser::Error::custom("intentional encode failure"))
}
}
#[test]
fn postcard_codec_reports_encode_errors() {
let error = PostcardCodec.encode(&FailingSerialize).unwrap_err();
assert!(matches!(error, CacheError::Encode(_)));
}
#[test]
fn postcard_codec_default_is_available() {
let codec = PostcardCodec;
let default_codec = PostcardCodec;
assert_eq!(format!("{codec:?}"), format!("{default_codec:?}"));
}
}