codeprism_storage/
serialization.rs

1//! Serialization utilities for storage
2
3use anyhow::Result;
4use serde::{Deserialize, Serialize};
5
6/// Serialization format
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum SerializationFormat {
9    Bincode,
10    Json,
11    MessagePack,
12}
13
14/// Compression algorithm
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum CompressionAlgorithm {
17    None,
18    Gzip,
19    Zstd,
20}
21
22/// Serializer with optional compression
23pub struct Serializer {
24    format: SerializationFormat,
25    compression: CompressionAlgorithm,
26}
27
28impl Serializer {
29    /// Create a new serializer
30    pub fn new(format: SerializationFormat, compression: CompressionAlgorithm) -> Self {
31        Self {
32            format,
33            compression,
34        }
35    }
36
37    /// Serialize and optionally compress data
38    pub fn serialize<T>(&self, value: &T) -> Result<Vec<u8>>
39    where
40        T: Serialize,
41    {
42        // First serialize
43        let serialized = match self.format {
44            SerializationFormat::Bincode => bincode::serialize(value)?,
45            SerializationFormat::Json => serde_json::to_vec(value)?,
46            SerializationFormat::MessagePack => rmp_serde::to_vec(value)?,
47        };
48
49        // Then optionally compress
50        let compressed = match self.compression {
51            CompressionAlgorithm::None => serialized,
52            CompressionAlgorithm::Gzip => {
53                use std::io::Write;
54                let mut encoder =
55                    flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::default());
56                encoder.write_all(&serialized)?;
57                encoder.finish()?
58            }
59            CompressionAlgorithm::Zstd => zstd::bulk::compress(&serialized, 3)?,
60        };
61
62        Ok(compressed)
63    }
64
65    /// Decompress and deserialize data
66    pub fn deserialize<T>(&self, data: &[u8]) -> Result<T>
67    where
68        T: for<'de> Deserialize<'de>,
69    {
70        // First decompress if needed
71        let decompressed = match self.compression {
72            CompressionAlgorithm::None => data.to_vec(),
73            CompressionAlgorithm::Gzip => {
74                use std::io::Read;
75                let mut decoder = flate2::read::GzDecoder::new(data);
76                let mut decompressed = Vec::new();
77                decoder.read_to_end(&mut decompressed)?;
78                decompressed
79            }
80            CompressionAlgorithm::Zstd => {
81                zstd::bulk::decompress(data, 10 * 1024 * 1024)? // 10MB max decompressed size
82            }
83        };
84
85        // Then deserialize
86        let value = match self.format {
87            SerializationFormat::Bincode => bincode::deserialize(&decompressed)?,
88            SerializationFormat::Json => serde_json::from_slice(&decompressed)?,
89            SerializationFormat::MessagePack => rmp_serde::from_slice(&decompressed)?,
90        };
91
92        Ok(value)
93    }
94}
95
96impl Default for Serializer {
97    /// Create a default serializer (bincode with gzip compression)
98    fn default() -> Self {
99        Self {
100            format: SerializationFormat::Bincode,
101            compression: CompressionAlgorithm::Gzip,
102        }
103    }
104}
105
106#[cfg(test)]
107mod tests {
108    use super::*;
109
110    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
111    struct TestData {
112        name: String,
113        value: i32,
114        items: Vec<String>,
115    }
116
117    #[test]
118    fn test_serialization_bincode() {
119        let serializer = Serializer::new(SerializationFormat::Bincode, CompressionAlgorithm::None);
120        let data = TestData {
121            name: "test".to_string(),
122            value: 42,
123            items: vec!["a".to_string(), "b".to_string()],
124        };
125
126        let serialized = serializer.serialize(&data).unwrap();
127        let deserialized: TestData = serializer.deserialize(&serialized).unwrap();
128
129        assert_eq!(data, deserialized);
130    }
131
132    #[test]
133    fn test_serialization_json() {
134        let serializer = Serializer::new(SerializationFormat::Json, CompressionAlgorithm::None);
135        let data = TestData {
136            name: "test".to_string(),
137            value: 42,
138            items: vec!["a".to_string(), "b".to_string()],
139        };
140
141        let serialized = serializer.serialize(&data).unwrap();
142        let deserialized: TestData = serializer.deserialize(&serialized).unwrap();
143
144        assert_eq!(data, deserialized);
145    }
146
147    #[test]
148    fn test_compression_gzip() {
149        let serializer = Serializer::new(SerializationFormat::Json, CompressionAlgorithm::Gzip);
150        let data = TestData {
151            name: "test".to_string(),
152            value: 42,
153            items: vec!["a".to_string(), "b".to_string()],
154        };
155
156        let serialized = serializer.serialize(&data).unwrap();
157        let deserialized: TestData = serializer.deserialize(&serialized).unwrap();
158
159        assert_eq!(data, deserialized);
160    }
161}