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 #[cfg(feature = "compression")]
144 {
145 use flate2::write::DeflateEncoder;
146 use flate2::Compression;
147 use std::io::Write;
148
149 let mut encoder = DeflateEncoder::new(Vec::new(), Compression::default());
150 encoder.write_all(data)?;
151 Ok(encoder.finish()?)
152 }
153 #[cfg(not(feature = "compression"))]
154 {
155 Ok(data.to_vec())
157 }
158 }
159
160 #[cfg(target_arch = "wasm32")]
161 fn compress(&self, data: &[u8]) -> Result<Vec<u8>, SerializationError> {
162 Ok(data.to_vec())
165 }
166
167 #[cfg(not(target_arch = "wasm32"))]
169 fn decompress(&self, data: &[u8]) -> Result<Vec<u8>, SerializationError> {
170 #[cfg(feature = "compression")]
171 {
172 use flate2::read::DeflateDecoder;
173 use std::io::Read;
174
175 let mut decoder = DeflateDecoder::new(data);
176 let mut decompressed = Vec::new();
177 decoder.read_to_end(&mut decompressed)?;
178 Ok(decompressed)
179 }
180 #[cfg(not(feature = "compression"))]
181 {
182 Ok(data.to_vec())
184 }
185 }
186
187 #[cfg(target_arch = "wasm32")]
188 fn decompress(&self, data: &[u8]) -> Result<Vec<u8>, SerializationError> {
189 Ok(data.to_vec())
192 }
193}
194
195impl Default for CRDTSerializer {
196 fn default() -> Self {
197 Self::new()
198 }
199}
200
201pub mod benchmark {
203 use super::*;
204 use std::time::Instant;
205
206 pub fn benchmark_serialization<T: Serialize + for<'de> Deserialize<'de>>(
208 data: &T,
209 iterations: usize,
210 ) -> SerializationBenchmark {
211 let mut bincode_serializer = Serializer::new(SerializationFormat::Bincode);
212 let mut json_serializer = Serializer::new(SerializationFormat::Json);
213
214 let _ = bincode_serializer.serialize(data);
216 let _ = json_serializer.serialize(data);
217
218 let start = Instant::now();
220 for _ in 0..iterations {
221 let _ = bincode_serializer.serialize(data);
222 }
223 let bincode_serialize_time = start.elapsed();
224
225 let serialized_bincode = bincode_serializer.serialize(data).unwrap();
226 let start = Instant::now();
227 for _ in 0..iterations {
228 let _ = bincode_serializer.deserialize::<T>(&serialized_bincode);
229 }
230 let bincode_deserialize_time = start.elapsed();
231
232 let start = Instant::now();
234 for _ in 0..iterations {
235 let _ = json_serializer.serialize(data);
236 }
237 let json_serialize_time = start.elapsed();
238
239 let serialized_json = json_serializer.serialize(data).unwrap();
240 let start = Instant::now();
241 for _ in 0..iterations {
242 let _ = json_serializer.deserialize::<T>(&serialized_json);
243 }
244 let json_deserialize_time = start.elapsed();
245
246 SerializationBenchmark {
247 bincode_serialize_time,
248 bincode_deserialize_time,
249 json_serialize_time,
250 json_deserialize_time,
251 bincode_size: serialized_bincode.len(),
252 json_size: serialized_json.len(),
253 iterations,
254 }
255 }
256
257 #[derive(Debug)]
259 pub struct SerializationBenchmark {
260 pub bincode_serialize_time: std::time::Duration,
261 pub bincode_deserialize_time: std::time::Duration,
262 pub json_serialize_time: std::time::Duration,
263 pub json_deserialize_time: std::time::Duration,
264 pub bincode_size: usize,
265 pub json_size: usize,
266 pub iterations: usize,
267 }
268
269 impl SerializationBenchmark {
270 pub fn serialize_improvement_ratio(&self) -> f64 {
272 self.json_serialize_time.as_nanos() as f64
273 / self.bincode_serialize_time.as_nanos() as f64
274 }
275
276 pub fn size_reduction_ratio(&self) -> f64 {
278 self.json_size as f64 / self.bincode_size as f64
279 }
280
281 pub fn print_summary(&self) {
283 println!("=== Serialization Benchmark Results ===");
284 println!("Iterations: {}", self.iterations);
285 println!();
286 println!("Bincode:");
287 println!(" Serialize: {:?}", self.bincode_serialize_time);
288 println!(" Deserialize: {:?}", self.bincode_deserialize_time);
289 println!(" Size: {} bytes", self.bincode_size);
290 println!();
291 println!("JSON:");
292 println!(" Serialize: {:?}", self.json_serialize_time);
293 println!(" Deserialize: {:?}", self.json_deserialize_time);
294 println!(" Size: {} bytes", self.json_size);
295 println!();
296 println!("Improvements:");
297 println!(
298 " Serialize: {:.2}x faster",
299 self.serialize_improvement_ratio()
300 );
301 println!(" Size: {:.2}x smaller", self.size_reduction_ratio());
302 }
303 }
304}
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309 use crate::crdt::{LwwRegister, ReplicaId};
310
311 #[test]
312 fn test_serialization_formats() {
313 let data = LwwRegister::new("test_value".to_string(), ReplicaId::default());
314
315 let bincode_serializer = Serializer::new(SerializationFormat::Bincode);
316 let json_serializer = Serializer::new(SerializationFormat::Json);
317
318 let bincode_bytes = bincode_serializer.serialize(&data).unwrap();
319 let json_bytes = json_serializer.serialize(&data).unwrap();
320
321 let bincode_deserialized: LwwRegister<String> =
322 bincode_serializer.deserialize(&bincode_bytes).unwrap();
323 let json_deserialized: LwwRegister<String> =
324 json_serializer.deserialize(&json_bytes).unwrap();
325
326 assert_eq!(data, bincode_deserialized);
327 assert_eq!(data, json_deserialized);
328 assert!(bincode_bytes.len() < json_bytes.len());
329 }
330
331 #[test]
332 fn test_crdt_serializer() {
333 let data = LwwRegister::new("test_value".to_string(), ReplicaId::default());
334 let serializer = CRDTSerializer::new();
335
336 let serialized = serializer.serialize_crdt(&data).unwrap();
337 let deserialized: LwwRegister<String> = serializer.deserialize_crdt(&serialized).unwrap();
338
339 assert_eq!(data, deserialized);
340 }
341
342 #[test]
343 fn test_serialization_benchmark() {
344 let data = LwwRegister::new("test_value".to_string(), ReplicaId::default());
345 let benchmark = benchmark::benchmark_serialization(&data, 1000);
346
347 assert!(benchmark.serialize_improvement_ratio() > 1.0);
349 assert!(benchmark.size_reduction_ratio() > 1.0);
350 }
351}