1use bytes::Bytes;
2use serde::{de::DeserializeOwned, Serialize};
3
4use crate::{CacheError, Result};
5
6pub trait CacheCodec: Clone + Send + Sync + 'static {
28 fn encode<T>(&self, value: &T) -> Result<Bytes>
30 where
31 T: Serialize;
32
33 fn decode<T>(&self, bytes: &Bytes) -> Result<T>
35 where
36 T: DeserializeOwned;
37}
38
39#[derive(Debug, Clone, Copy, Default)]
44pub struct PostcardCodec;
45
46impl CacheCodec for PostcardCodec {
47 fn encode<T>(&self, value: &T) -> Result<Bytes>
48 where
49 T: Serialize,
50 {
51 postcard::to_allocvec(value)
52 .map(Bytes::from)
53 .map_err(|source| CacheError::Encode(source.to_string()))
54 }
55
56 fn decode<T>(&self, bytes: &Bytes) -> Result<T>
57 where
58 T: DeserializeOwned,
59 {
60 postcard::from_bytes(bytes).map_err(|source| CacheError::Decode(source.to_string()))
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use serde::ser::{Serialize, Serializer};
67
68 use super::*;
69
70 struct FailingSerialize;
71
72 impl Serialize for FailingSerialize {
73 fn serialize<S>(&self, _serializer: S) -> std::result::Result<S::Ok, S::Error>
74 where
75 S: Serializer,
76 {
77 Err(serde::ser::Error::custom("intentional encode failure"))
78 }
79 }
80
81 #[test]
82 fn postcard_codec_reports_encode_errors() {
83 let error = PostcardCodec.encode(&FailingSerialize).unwrap_err();
84
85 assert!(matches!(error, CacheError::Encode(_)));
86 }
87
88 #[test]
89 fn postcard_codec_default_is_available() {
90 let codec = PostcardCodec;
91 let default_codec = PostcardCodec;
92
93 assert_eq!(format!("{codec:?}"), format!("{default_codec:?}"));
94 }
95}