skp_cache_core/traits/
serializer.rs

1//! Pluggable serialization trait
2
3use crate::CacheError;
4use serde::{de::DeserializeOwned, Serialize};
5
6/// Trait for pluggable serialization formats
7///
8/// Implement this trait to add custom serialization formats.
9/// Built-in implementations: JSON, MessagePack, Bincode.
10pub trait Serializer: Send + Sync + Clone + 'static {
11    /// Name of the serializer (for debugging/metrics)
12    fn name(&self) -> &str;
13
14    /// Serialize a value to bytes
15    fn serialize<T: Serialize>(&self, value: &T) -> Result<Vec<u8>, CacheError>;
16
17    /// Deserialize bytes to a value
18    fn deserialize<T: DeserializeOwned>(&self, bytes: &[u8]) -> Result<T, CacheError>;
19}
20
21/// JSON serializer (default)
22///
23/// Human-readable, widely compatible, good for debugging.
24#[derive(Debug, Clone, Copy, Default)]
25pub struct JsonSerializer;
26
27impl Serializer for JsonSerializer {
28    fn name(&self) -> &str {
29        "json"
30    }
31
32    fn serialize<T: Serialize>(&self, value: &T) -> Result<Vec<u8>, CacheError> {
33        serde_json::to_vec(value).map_err(|e| CacheError::Serialization(e.to_string()))
34    }
35
36    fn deserialize<T: DeserializeOwned>(&self, bytes: &[u8]) -> Result<T, CacheError> {
37        serde_json::from_slice(bytes).map_err(|e| CacheError::Deserialization(e.to_string()))
38    }
39}
40
41/// MessagePack serializer (optional)
42///
43/// Faster and more compact than JSON, but not human-readable.
44/// Enable with `msgpack` feature.
45#[cfg(feature = "msgpack")]
46#[derive(Debug, Clone, Copy, Default)]
47pub struct MsgPackSerializer;
48
49#[cfg(feature = "msgpack")]
50impl Serializer for MsgPackSerializer {
51    fn name(&self) -> &str {
52        "msgpack"
53    }
54
55    fn serialize<T: Serialize>(&self, value: &T) -> Result<Vec<u8>, CacheError> {
56        rmp_serde::to_vec(value).map_err(|e| CacheError::Serialization(e.to_string()))
57    }
58
59    fn deserialize<T: DeserializeOwned>(&self, bytes: &[u8]) -> Result<T, CacheError> {
60        rmp_serde::from_slice(bytes).map_err(|e| CacheError::Deserialization(e.to_string()))
61    }
62}
63
64/// Bincode serializer (optional)
65///
66/// Fastest and most compact, but not human-readable or cross-language.
67/// Enable with `bincode` feature.
68#[cfg(feature = "bincode")]
69#[derive(Debug, Clone, Copy, Default)]
70pub struct BincodeSerializer;
71
72#[cfg(feature = "bincode")]
73impl Serializer for BincodeSerializer {
74    fn name(&self) -> &str {
75        "bincode"
76    }
77
78    fn serialize<T: Serialize>(&self, value: &T) -> Result<Vec<u8>, CacheError> {
79        bincode::serde::encode_to_vec(value, bincode::config::standard())
80            .map_err(|e| CacheError::Serialization(e.to_string()))
81    }
82
83    fn deserialize<T: DeserializeOwned>(&self, bytes: &[u8]) -> Result<T, CacheError> {
84        let (val, _len) = bincode::serde::decode_from_slice(bytes, bincode::config::standard())
85            .map_err(|e| CacheError::Deserialization(e.to_string()))?;
86        Ok(val)
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn test_json_roundtrip() {
96        let serializer = JsonSerializer;
97        let value = vec![1, 2, 3, 4, 5];
98
99        let bytes = serializer.serialize(&value).unwrap();
100        let decoded: Vec<i32> = serializer.deserialize(&bytes).unwrap();
101
102        assert_eq!(value, decoded);
103    }
104
105    #[test]
106    fn test_json_struct() {
107        #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
108        struct TestStruct {
109            name: String,
110            value: i32,
111        }
112
113        let serializer = JsonSerializer;
114        let value = TestStruct {
115            name: "test".to_string(),
116            value: 42,
117        };
118
119        let bytes = serializer.serialize(&value).unwrap();
120        let decoded: TestStruct = serializer.deserialize(&bytes).unwrap();
121
122        assert_eq!(value, decoded);
123    }
124
125    #[test]
126    fn test_json_serializer_name() {
127        assert_eq!(JsonSerializer.name(), "json");
128    }
129}