1use crate::{ContentEncoding, ContentType};
19use serde::{de::DeserializeOwned, Serialize};
20use std::fmt;
21
22#[derive(Debug)]
24pub enum SerializerError {
25 Serialize(String),
27 Deserialize(String),
29 UnsupportedContentType(String),
31 Compression(String),
33}
34
35impl fmt::Display for SerializerError {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 match self {
38 SerializerError::Serialize(msg) => write!(f, "Serialization error: {}", msg),
39 SerializerError::Deserialize(msg) => write!(f, "Deserialization error: {}", msg),
40 SerializerError::UnsupportedContentType(ct) => {
41 write!(f, "Unsupported content type: {}", ct)
42 }
43 SerializerError::Compression(msg) => write!(f, "Compression error: {}", msg),
44 }
45 }
46}
47
48impl std::error::Error for SerializerError {}
49
50pub type SerializerResult<T> = Result<T, SerializerError>;
52
53pub trait Serializer: Send + Sync {
58 fn content_type(&self) -> ContentType;
60
61 fn content_encoding(&self) -> ContentEncoding;
63
64 fn serialize<T: Serialize>(&self, value: &T) -> SerializerResult<Vec<u8>>;
66
67 fn deserialize<T: DeserializeOwned>(&self, bytes: &[u8]) -> SerializerResult<T>;
69
70 fn name(&self) -> &'static str;
72}
73
74#[derive(Debug, Clone, Copy, Default)]
76pub struct JsonSerializer;
77
78impl Serializer for JsonSerializer {
79 #[inline]
80 fn content_type(&self) -> ContentType {
81 ContentType::Json
82 }
83
84 #[inline]
85 fn content_encoding(&self) -> ContentEncoding {
86 ContentEncoding::Utf8
87 }
88
89 fn serialize<T: Serialize>(&self, value: &T) -> SerializerResult<Vec<u8>> {
90 serde_json::to_vec(value).map_err(|e| SerializerError::Serialize(e.to_string()))
91 }
92
93 fn deserialize<T: DeserializeOwned>(&self, bytes: &[u8]) -> SerializerResult<T> {
94 serde_json::from_slice(bytes).map_err(|e| SerializerError::Deserialize(e.to_string()))
95 }
96
97 #[inline]
98 fn name(&self) -> &'static str {
99 "json"
100 }
101}
102
103#[cfg(feature = "msgpack")]
105#[derive(Debug, Clone, Copy, Default)]
106pub struct MessagePackSerializer;
107
108#[cfg(feature = "msgpack")]
109impl Serializer for MessagePackSerializer {
110 #[inline]
111 fn content_type(&self) -> ContentType {
112 ContentType::MessagePack
113 }
114
115 #[inline]
116 fn content_encoding(&self) -> ContentEncoding {
117 ContentEncoding::Binary
118 }
119
120 fn serialize<T: Serialize>(&self, value: &T) -> SerializerResult<Vec<u8>> {
121 rmp_serde::to_vec(value).map_err(|e| SerializerError::Serialize(e.to_string()))
122 }
123
124 fn deserialize<T: DeserializeOwned>(&self, bytes: &[u8]) -> SerializerResult<T> {
125 rmp_serde::from_slice(bytes).map_err(|e| SerializerError::Deserialize(e.to_string()))
126 }
127
128 #[inline]
129 fn name(&self) -> &'static str {
130 "msgpack"
131 }
132}
133
134#[cfg(feature = "yaml")]
136#[derive(Debug, Clone, Copy, Default)]
137pub struct YamlSerializer;
138
139#[cfg(feature = "yaml")]
140impl Serializer for YamlSerializer {
141 #[inline]
142 fn content_type(&self) -> ContentType {
143 ContentType::Custom("application/x-yaml".to_string())
144 }
145
146 #[inline]
147 fn content_encoding(&self) -> ContentEncoding {
148 ContentEncoding::Utf8
149 }
150
151 fn serialize<T: Serialize>(&self, value: &T) -> SerializerResult<Vec<u8>> {
152 serde_yaml::to_string(value)
153 .map(|s| s.into_bytes())
154 .map_err(|e| SerializerError::Serialize(e.to_string()))
155 }
156
157 fn deserialize<T: DeserializeOwned>(&self, bytes: &[u8]) -> SerializerResult<T> {
158 serde_yaml::from_slice(bytes).map_err(|e| SerializerError::Deserialize(e.to_string()))
159 }
160
161 #[inline]
162 fn name(&self) -> &'static str {
163 "yaml"
164 }
165}
166
167#[cfg(feature = "bson-format")]
169#[derive(Debug, Clone, Copy, Default)]
170pub struct BsonSerializer;
171
172#[cfg(feature = "bson-format")]
173impl Serializer for BsonSerializer {
174 #[inline]
175 fn content_type(&self) -> ContentType {
176 ContentType::Custom("application/bson".to_string())
177 }
178
179 #[inline]
180 fn content_encoding(&self) -> ContentEncoding {
181 ContentEncoding::Binary
182 }
183
184 fn serialize<T: Serialize>(&self, value: &T) -> SerializerResult<Vec<u8>> {
185 bson::serialize_to_vec(value).map_err(|e| SerializerError::Serialize(e.to_string()))
186 }
187
188 fn deserialize<T: DeserializeOwned>(&self, bytes: &[u8]) -> SerializerResult<T> {
189 bson::deserialize_from_slice(bytes).map_err(|e| SerializerError::Deserialize(e.to_string()))
190 }
191
192 #[inline]
193 fn name(&self) -> &'static str {
194 "bson"
195 }
196}
197
198#[cfg(feature = "protobuf")]
204#[derive(Debug, Clone, Copy, Default)]
205pub struct ProtobufSerializer;
206
207#[cfg(feature = "protobuf")]
208impl ProtobufSerializer {
209 pub fn serialize_message<T: prost::Message>(&self, value: &T) -> SerializerResult<Vec<u8>> {
211 let mut buf = Vec::new();
212 value
213 .encode(&mut buf)
214 .map_err(|e| SerializerError::Serialize(e.to_string()))?;
215 Ok(buf)
216 }
217
218 pub fn deserialize_message<T: prost::Message + Default>(
220 &self,
221 bytes: &[u8],
222 ) -> SerializerResult<T> {
223 T::decode(bytes).map_err(|e| SerializerError::Deserialize(e.to_string()))
224 }
225
226 #[inline]
228 pub fn content_type(&self) -> ContentType {
229 ContentType::Custom("application/protobuf".to_string())
230 }
231
232 #[inline]
234 pub fn content_encoding(&self) -> ContentEncoding {
235 ContentEncoding::Binary
236 }
237
238 #[inline]
240 pub fn name(&self) -> &'static str {
241 "protobuf"
242 }
243}
244
245#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
247pub enum SerializerType {
248 #[default]
250 Json,
251 #[cfg(feature = "msgpack")]
253 MessagePack,
254 #[cfg(feature = "yaml")]
256 Yaml,
257 #[cfg(feature = "bson-format")]
259 Bson,
260}
261
262impl SerializerType {
263 pub fn from_content_type(content_type: &str) -> SerializerResult<Self> {
265 match content_type {
266 "application/json" => Ok(SerializerType::Json),
267 #[cfg(feature = "msgpack")]
268 "application/x-msgpack" => Ok(SerializerType::MessagePack),
269 #[cfg(feature = "yaml")]
270 "application/x-yaml" | "application/yaml" | "text/yaml" => Ok(SerializerType::Yaml),
271 #[cfg(feature = "bson-format")]
272 "application/bson" => Ok(SerializerType::Bson),
273 _ => Err(SerializerError::UnsupportedContentType(
274 content_type.to_string(),
275 )),
276 }
277 }
278
279 pub fn serialize<T: Serialize>(&self, value: &T) -> SerializerResult<Vec<u8>> {
281 match self {
282 SerializerType::Json => JsonSerializer.serialize(value),
283 #[cfg(feature = "msgpack")]
284 SerializerType::MessagePack => MessagePackSerializer.serialize(value),
285 #[cfg(feature = "yaml")]
286 SerializerType::Yaml => YamlSerializer.serialize(value),
287 #[cfg(feature = "bson-format")]
288 SerializerType::Bson => BsonSerializer.serialize(value),
289 }
290 }
291
292 pub fn deserialize<T: DeserializeOwned>(&self, bytes: &[u8]) -> SerializerResult<T> {
294 match self {
295 SerializerType::Json => JsonSerializer.deserialize(bytes),
296 #[cfg(feature = "msgpack")]
297 SerializerType::MessagePack => MessagePackSerializer.deserialize(bytes),
298 #[cfg(feature = "yaml")]
299 SerializerType::Yaml => YamlSerializer.deserialize(bytes),
300 #[cfg(feature = "bson-format")]
301 SerializerType::Bson => BsonSerializer.deserialize(bytes),
302 }
303 }
304
305 #[inline]
307 pub fn content_type(&self) -> ContentType {
308 match self {
309 SerializerType::Json => JsonSerializer.content_type(),
310 #[cfg(feature = "msgpack")]
311 SerializerType::MessagePack => MessagePackSerializer.content_type(),
312 #[cfg(feature = "yaml")]
313 SerializerType::Yaml => YamlSerializer.content_type(),
314 #[cfg(feature = "bson-format")]
315 SerializerType::Bson => BsonSerializer.content_type(),
316 }
317 }
318
319 #[inline]
321 pub fn content_encoding(&self) -> ContentEncoding {
322 match self {
323 SerializerType::Json => JsonSerializer.content_encoding(),
324 #[cfg(feature = "msgpack")]
325 SerializerType::MessagePack => MessagePackSerializer.content_encoding(),
326 #[cfg(feature = "yaml")]
327 SerializerType::Yaml => YamlSerializer.content_encoding(),
328 #[cfg(feature = "bson-format")]
329 SerializerType::Bson => BsonSerializer.content_encoding(),
330 }
331 }
332
333 #[inline]
335 pub fn name(&self) -> &'static str {
336 match self {
337 SerializerType::Json => JsonSerializer.name(),
338 #[cfg(feature = "msgpack")]
339 SerializerType::MessagePack => MessagePackSerializer.name(),
340 #[cfg(feature = "yaml")]
341 SerializerType::Yaml => YamlSerializer.name(),
342 #[cfg(feature = "bson-format")]
343 SerializerType::Bson => BsonSerializer.name(),
344 }
345 }
346}
347
348impl fmt::Display for SerializerType {
349 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350 write!(f, "{}", self.name())
351 }
352}
353
354impl TryFrom<&str> for SerializerType {
355 type Error = SerializerError;
356
357 fn try_from(content_type: &str) -> Result<Self, Self::Error> {
358 Self::from_content_type(content_type)
359 }
360}
361
362pub fn get_serializer(content_type: &str) -> SerializerResult<SerializerType> {
374 SerializerType::from_content_type(content_type)
375}
376
377pub struct SerializerRegistry {
379 default: SerializerType,
380}
381
382impl Default for SerializerRegistry {
383 fn default() -> Self {
384 Self::new()
385 }
386}
387
388impl SerializerRegistry {
389 pub fn new() -> Self {
391 Self {
392 default: SerializerType::Json,
393 }
394 }
395
396 #[inline]
398 pub fn default_serializer(&self) -> SerializerType {
399 self.default
400 }
401
402 pub fn get(&self, content_type: &str) -> SerializerResult<SerializerType> {
404 get_serializer(content_type)
405 }
406
407 pub fn available() -> Vec<&'static str> {
409 vec![
410 "application/json",
411 #[cfg(feature = "msgpack")]
412 "application/x-msgpack",
413 #[cfg(feature = "yaml")]
414 "application/x-yaml",
415 #[cfg(feature = "bson-format")]
416 "application/bson",
417 ]
418 }
419}
420
421#[cfg(test)]
422mod tests {
423 use super::*;
424 use serde::{Deserialize, Serialize};
425
426 #[derive(Debug, PartialEq, Serialize, Deserialize)]
427 struct TestData {
428 name: String,
429 value: i32,
430 }
431
432 #[test]
433 fn test_json_serializer_round_trip() {
434 let serializer = JsonSerializer;
435 let data = TestData {
436 name: "test".to_string(),
437 value: 42,
438 };
439
440 let bytes = serializer.serialize(&data).unwrap();
441 let decoded: TestData = serializer.deserialize(&bytes).unwrap();
442
443 assert_eq!(data, decoded);
444 }
445
446 #[test]
447 fn test_json_serializer_content_type() {
448 let serializer = JsonSerializer;
449 assert_eq!(serializer.content_type(), ContentType::Json);
450 assert_eq!(serializer.content_encoding(), ContentEncoding::Utf8);
451 assert_eq!(serializer.name(), "json");
452 }
453
454 #[cfg(feature = "msgpack")]
455 #[test]
456 fn test_msgpack_serializer_round_trip() {
457 let serializer = MessagePackSerializer;
458 let data = TestData {
459 name: "msgpack_test".to_string(),
460 value: 100,
461 };
462
463 let bytes = serializer.serialize(&data).unwrap();
464 let decoded: TestData = serializer.deserialize(&bytes).unwrap();
465
466 assert_eq!(data, decoded);
467 }
468
469 #[cfg(feature = "msgpack")]
470 #[test]
471 fn test_msgpack_serializer_content_type() {
472 let serializer = MessagePackSerializer;
473 assert_eq!(serializer.content_type(), ContentType::MessagePack);
474 assert_eq!(serializer.content_encoding(), ContentEncoding::Binary);
475 assert_eq!(serializer.name(), "msgpack");
476 }
477
478 #[test]
479 fn test_get_serializer_json() {
480 let serializer = get_serializer("application/json").unwrap();
481 assert_eq!(serializer.name(), "json");
482 }
483
484 #[cfg(feature = "msgpack")]
485 #[test]
486 fn test_get_serializer_msgpack() {
487 let serializer = get_serializer("application/x-msgpack").unwrap();
488 assert_eq!(serializer.name(), "msgpack");
489 }
490
491 #[test]
492 fn test_get_serializer_unsupported() {
493 let result = get_serializer("application/unsupported");
494 assert!(result.is_err());
495 match result {
496 Err(SerializerError::UnsupportedContentType(ct)) => {
497 assert_eq!(ct, "application/unsupported");
498 }
499 _ => panic!("Expected UnsupportedContentType error"),
500 }
501 }
502
503 #[test]
504 fn test_serializer_registry() {
505 let registry = SerializerRegistry::new();
506 assert_eq!(registry.default_serializer().name(), "json");
507
508 let json = registry.get("application/json").unwrap();
509 assert_eq!(json.name(), "json");
510 }
511
512 #[test]
513 fn test_serializer_registry_available() {
514 let available = SerializerRegistry::available();
515 assert!(available.contains(&"application/json"));
516 }
517
518 #[test]
519 fn test_serializer_error_display() {
520 let err = SerializerError::Serialize("test error".to_string());
521 assert_eq!(err.to_string(), "Serialization error: test error");
522
523 let err = SerializerError::Deserialize("parse failed".to_string());
524 assert_eq!(err.to_string(), "Deserialization error: parse failed");
525
526 let err = SerializerError::UnsupportedContentType("text/plain".to_string());
527 assert_eq!(err.to_string(), "Unsupported content type: text/plain");
528
529 let err = SerializerError::Compression("gzip failed".to_string());
530 assert_eq!(err.to_string(), "Compression error: gzip failed");
531 }
532
533 #[cfg(feature = "bson-format")]
534 #[test]
535 fn test_bson_serializer_round_trip() {
536 let serializer = BsonSerializer;
537 let data = TestData {
538 name: "bson_test".to_string(),
539 value: 200,
540 };
541
542 let bytes = serializer.serialize(&data).unwrap();
543 let decoded: TestData = serializer.deserialize(&bytes).unwrap();
544
545 assert_eq!(data, decoded);
546 }
547
548 #[cfg(feature = "bson-format")]
549 #[test]
550 fn test_bson_serializer_content_type() {
551 let serializer = BsonSerializer;
552 assert_eq!(
553 serializer.content_type(),
554 ContentType::Custom("application/bson".to_string())
555 );
556 assert_eq!(serializer.content_encoding(), ContentEncoding::Binary);
557 assert_eq!(serializer.name(), "bson");
558 }
559
560 #[cfg(feature = "bson-format")]
561 #[test]
562 fn test_get_serializer_bson() {
563 let serializer = get_serializer("application/bson").unwrap();
564 assert_eq!(serializer.name(), "bson");
565 }
566
567 #[test]
568 fn test_serializer_type_equality() {
569 let json1 = SerializerType::Json;
570 let json2 = SerializerType::Json;
571 assert_eq!(json1, json2);
572
573 #[cfg(feature = "msgpack")]
574 {
575 let msgpack = SerializerType::MessagePack;
576 assert_ne!(json1, msgpack);
577 }
578 }
579
580 #[test]
581 fn test_serializer_type_hash() {
582 use std::collections::HashSet;
583
584 let mut set = HashSet::new();
585 set.insert(SerializerType::Json);
586 set.insert(SerializerType::Json); #[cfg(feature = "msgpack")]
589 set.insert(SerializerType::MessagePack);
590
591 #[cfg(feature = "msgpack")]
592 assert_eq!(set.len(), 2);
593
594 #[cfg(not(feature = "msgpack"))]
595 assert_eq!(set.len(), 1);
596
597 assert!(set.contains(&SerializerType::Json));
598 }
599
600 #[test]
601 fn test_serializer_type_display() {
602 assert_eq!(SerializerType::Json.to_string(), "json");
603
604 #[cfg(feature = "msgpack")]
605 assert_eq!(SerializerType::MessagePack.to_string(), "msgpack");
606
607 #[cfg(feature = "yaml")]
608 assert_eq!(SerializerType::Yaml.to_string(), "yaml");
609
610 #[cfg(feature = "bson-format")]
611 assert_eq!(SerializerType::Bson.to_string(), "bson");
612 }
613
614 #[test]
615 fn test_serializer_type_try_from() {
616 use std::convert::TryFrom;
617
618 let json = SerializerType::try_from("application/json").unwrap();
619 assert_eq!(json, SerializerType::Json);
620
621 #[cfg(feature = "msgpack")]
622 {
623 let msgpack = SerializerType::try_from("application/x-msgpack").unwrap();
624 assert_eq!(msgpack, SerializerType::MessagePack);
625 }
626
627 #[cfg(feature = "yaml")]
628 {
629 let yaml = SerializerType::try_from("application/yaml").unwrap();
630 assert_eq!(yaml, SerializerType::Yaml);
631 }
632
633 let result = SerializerType::try_from("application/unsupported");
635 assert!(result.is_err());
636 }
637
638 #[test]
639 fn test_serializer_type_default() {
640 let default_type = SerializerType::default();
641 assert_eq!(default_type, SerializerType::Json);
642 }
643
644 #[test]
645 fn test_serializer_type_copy() {
646 let json = SerializerType::Json;
647 let json_copy = json; let _json_original = json; assert_eq!(json_copy, SerializerType::Json);
651 }
652}