leptos_sync_core/
serialization.rs1use serde::{Deserialize, Serialize};
4use std::io;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum SerializationFormat {
9 Bincode,
11 Json,
13}
14
15impl Default for SerializationFormat {
16 fn default() -> Self {
17 Self::Bincode
18 }
19}
20
21#[derive(Debug, thiserror::Error)]
23pub enum SerializationError {
24 #[error("Bincode serialization error: {0}")]
25 Bincode(#[from] bincode::Error),
26 #[error("JSON serialization error: {0}")]
27 Json(#[from] serde_json::Error),
28 #[error("IO error: {0}")]
29 Io(#[from] io::Error),
30}
31
32pub struct Serializer {
34 format: SerializationFormat,
35}
36
37impl Serializer {
38 pub fn new(format: SerializationFormat) -> Self {
40 Self { format }
41 }
42
43 pub fn default() -> Self {
45 Self::new(SerializationFormat::default())
46 }
47
48 pub fn serialize<T: Serialize>(&self, value: &T) -> Result<Vec<u8>, SerializationError> {
50 match self.format {
51 SerializationFormat::Bincode => {
52 bincode::serialize(value).map_err(SerializationError::Bincode)
53 }
54 SerializationFormat::Json => {
55 serde_json::to_vec(value).map_err(SerializationError::Json)
56 }
57 }
58 }
59
60 pub fn deserialize<T: for<'de> Deserialize<'de>>(
62 &self,
63 bytes: &[u8],
64 ) -> Result<T, SerializationError> {
65 match self.format {
66 SerializationFormat::Bincode => {
67 bincode::deserialize(bytes).map_err(SerializationError::Bincode)
68 }
69 SerializationFormat::Json => {
70 serde_json::from_slice(bytes).map_err(SerializationError::Json)
71 }
72 }
73 }
74
75 pub fn format(&self) -> SerializationFormat {
77 self.format
78 }
79
80 pub fn set_format(&mut self, format: SerializationFormat) {
82 self.format = format;
83 }
84}
85
86pub struct CRDTSerializer {
88 serializer: Serializer,
89 compression_enabled: bool,
90}
91
92impl CRDTSerializer {
93 pub fn new() -> Self {
95 Self {
96 serializer: Serializer::new(SerializationFormat::Bincode),
97 compression_enabled: true,
98 }
99 }
100
101 pub fn with_settings(format: SerializationFormat, compression: bool) -> Self {
103 Self {
104 serializer: Serializer::new(format),
105 compression_enabled: compression,
106 }
107 }
108
109 pub fn serialize_crdt<T: Serialize>(&self, value: &T) -> Result<Vec<u8>, SerializationError> {
111 let serialized = self.serializer.serialize(value)?;
112
113 if self.compression_enabled && serialized.len() > 1024 {
114 self.compress(&serialized)
116 } else {
117 Ok(serialized)
118 }
119 }
120
121 pub fn deserialize_crdt<T: for<'de> Deserialize<'de>>(
123 &self,
124 bytes: &[u8],
125 ) -> Result<T, SerializationError> {
126 if self.is_compressed(bytes) {
127 let decompressed = self.decompress(bytes)?;
128 self.serializer.deserialize(&decompressed)
129 } else {
130 self.serializer.deserialize(bytes)
131 }
132 }
133
134 fn is_compressed(&self, bytes: &[u8]) -> bool {
136 bytes.len() > 0 && bytes[0] == 0x78 && bytes[1] == 0x9C
138 }
139
140 #[cfg(not(target_arch = "wasm32"))]
142 fn compress(&self, data: &[u8]) -> Result<Vec<u8>, SerializationError> {
143 use flate2::write::DeflateEncoder;
144 use flate2::Compression;
145 use std::io::Write;
146
147 let mut encoder = DeflateEncoder::new(Vec::new(), Compression::default());
148 encoder.write_all(data)?;
149 Ok(encoder.finish()?)
150 }
151
152 #[cfg(target_arch = "wasm32")]
153 fn compress(&self, data: &[u8]) -> Result<Vec<u8>, SerializationError> {
154 Ok(data.to_vec())
157 }
158
159 #[cfg(not(target_arch = "wasm32"))]
161 fn decompress(&self, data: &[u8]) -> Result<Vec<u8>, SerializationError> {
162 use flate2::read::DeflateDecoder;
163 use std::io::Read;
164
165 let mut decoder = DeflateDecoder::new(data);
166 let mut decompressed = Vec::new();
167 decoder.read_to_end(&mut decompressed)?;
168 Ok(decompressed)
169 }
170
171 #[cfg(target_arch = "wasm32")]
172 fn decompress(&self, data: &[u8]) -> Result<Vec<u8>, SerializationError> {
173 Ok(data.to_vec())
176 }
177}
178
179impl Default for CRDTSerializer {
180 fn default() -> Self {
181 Self::new()
182 }
183}
184
185pub mod benchmark {
187 use super::*;
188 use std::time::Instant;
189
190 pub fn benchmark_serialization<T: Serialize + for<'de> Deserialize<'de>>(
192 data: &T,
193 iterations: usize,
194 ) -> SerializationBenchmark {
195 let mut bincode_serializer = Serializer::new(SerializationFormat::Bincode);
196 let mut json_serializer = Serializer::new(SerializationFormat::Json);
197
198 let _ = bincode_serializer.serialize(data);
200 let _ = json_serializer.serialize(data);
201
202 let start = Instant::now();
204 for _ in 0..iterations {
205 let _ = bincode_serializer.serialize(data);
206 }
207 let bincode_serialize_time = start.elapsed();
208
209 let serialized_bincode = bincode_serializer.serialize(data).unwrap();
210 let start = Instant::now();
211 for _ in 0..iterations {
212 let _ = bincode_serializer.deserialize::<T>(&serialized_bincode);
213 }
214 let bincode_deserialize_time = start.elapsed();
215
216 let start = Instant::now();
218 for _ in 0..iterations {
219 let _ = json_serializer.serialize(data);
220 }
221 let json_serialize_time = start.elapsed();
222
223 let serialized_json = json_serializer.serialize(data).unwrap();
224 let start = Instant::now();
225 for _ in 0..iterations {
226 let _ = json_serializer.deserialize::<T>(&serialized_json);
227 }
228 let json_deserialize_time = start.elapsed();
229
230 SerializationBenchmark {
231 bincode_serialize_time,
232 bincode_deserialize_time,
233 json_serialize_time,
234 json_deserialize_time,
235 bincode_size: serialized_bincode.len(),
236 json_size: serialized_json.len(),
237 iterations,
238 }
239 }
240
241 #[derive(Debug)]
243 pub struct SerializationBenchmark {
244 pub bincode_serialize_time: std::time::Duration,
245 pub bincode_deserialize_time: std::time::Duration,
246 pub json_serialize_time: std::time::Duration,
247 pub json_deserialize_time: std::time::Duration,
248 pub bincode_size: usize,
249 pub json_size: usize,
250 pub iterations: usize,
251 }
252
253 impl SerializationBenchmark {
254 pub fn serialize_improvement_ratio(&self) -> f64 {
256 self.json_serialize_time.as_nanos() as f64 / self.bincode_serialize_time.as_nanos() as f64
257 }
258
259 pub fn size_reduction_ratio(&self) -> f64 {
261 self.json_size as f64 / self.bincode_size as f64
262 }
263
264 pub fn print_summary(&self) {
266 println!("=== Serialization Benchmark Results ===");
267 println!("Iterations: {}", self.iterations);
268 println!();
269 println!("Bincode:");
270 println!(" Serialize: {:?}", self.bincode_serialize_time);
271 println!(" Deserialize: {:?}", self.bincode_deserialize_time);
272 println!(" Size: {} bytes", self.bincode_size);
273 println!();
274 println!("JSON:");
275 println!(" Serialize: {:?}", self.json_serialize_time);
276 println!(" Deserialize: {:?}", self.json_deserialize_time);
277 println!(" Size: {} bytes", self.json_size);
278 println!();
279 println!("Improvements:");
280 println!(" Serialize: {:.2}x faster", self.serialize_improvement_ratio());
281 println!(" Size: {:.2}x smaller", self.size_reduction_ratio());
282 }
283 }
284}
285
286#[cfg(test)]
287mod tests {
288 use super::*;
289 use crate::crdt::{LwwRegister, ReplicaId};
290
291 #[test]
292 fn test_serialization_formats() {
293 let data = LwwRegister::new("test_value".to_string(), ReplicaId::default());
294
295 let bincode_serializer = Serializer::new(SerializationFormat::Bincode);
296 let json_serializer = Serializer::new(SerializationFormat::Json);
297
298 let bincode_bytes = bincode_serializer.serialize(&data).unwrap();
299 let json_bytes = json_serializer.serialize(&data).unwrap();
300
301 let bincode_deserialized: LwwRegister<String> = bincode_serializer.deserialize(&bincode_bytes).unwrap();
302 let json_deserialized: LwwRegister<String> = json_serializer.deserialize(&json_bytes).unwrap();
303
304 assert_eq!(data, bincode_deserialized);
305 assert_eq!(data, json_deserialized);
306 assert!(bincode_bytes.len() < json_bytes.len());
307 }
308
309 #[test]
310 fn test_crdt_serializer() {
311 let data = LwwRegister::new("test_value".to_string(), ReplicaId::default());
312 let serializer = CRDTSerializer::new();
313
314 let serialized = serializer.serialize_crdt(&data).unwrap();
315 let deserialized: LwwRegister<String> = serializer.deserialize_crdt(&serialized).unwrap();
316
317 assert_eq!(data, deserialized);
318 }
319
320 #[test]
321 fn test_serialization_benchmark() {
322 let data = LwwRegister::new("test_value".to_string(), ReplicaId::default());
323 let benchmark = benchmark::benchmark_serialization(&data, 1000);
324
325 assert!(benchmark.serialize_improvement_ratio() > 1.0);
327 assert!(benchmark.size_reduction_ratio() > 1.0);
328 }
329}