hydracache_core/codec.rs
1use bytes::Bytes;
2use serde::{de::DeserializeOwned, Serialize};
3
4use crate::{CacheError, Result};
5
6/// Serialization boundary for cached values.
7///
8/// Implement this trait to replace the default [`PostcardCodec`].
9///
10/// # Example
11///
12/// ```rust
13/// use hydracache_core::{CacheCodec, PostcardCodec};
14/// use serde::{Deserialize, Serialize};
15///
16/// #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
17/// struct User {
18/// id: u64,
19/// }
20///
21/// let codec = PostcardCodec;
22/// let bytes = codec.encode(&User { id: 1 }).unwrap();
23/// let decoded: User = codec.decode(&bytes).unwrap();
24///
25/// assert_eq!(decoded, User { id: 1 });
26/// ```
27pub trait CacheCodec: Clone + Send + Sync + 'static {
28 /// Encode a typed value into bytes.
29 fn encode<T>(&self, value: &T) -> Result<Bytes>
30 where
31 T: Serialize;
32
33 /// Decode bytes back into a typed value.
34 fn decode<T>(&self, bytes: &Bytes) -> Result<T>
35 where
36 T: DeserializeOwned;
37}
38
39/// Default compact binary codec for v0.
40///
41/// `PostcardCodec` is compact and works well for local cache values that derive
42/// `serde::Serialize` and `serde::Deserialize`.
43#[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}