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 #[cfg(feature = "protobuf")]
262 Protobuf,
263}
264
265impl SerializerType {
266 pub fn from_content_type(content_type: &str) -> SerializerResult<Self> {
268 match content_type {
269 "application/json" => Ok(SerializerType::Json),
270 #[cfg(feature = "msgpack")]
271 "application/x-msgpack" => Ok(SerializerType::MessagePack),
272 #[cfg(feature = "yaml")]
273 "application/x-yaml" | "application/yaml" | "text/yaml" => Ok(SerializerType::Yaml),
274 #[cfg(feature = "bson-format")]
275 "application/bson" => Ok(SerializerType::Bson),
276 #[cfg(feature = "protobuf")]
277 "application/protobuf" | "application/x-protobuf" => Ok(SerializerType::Protobuf),
278 _ => Err(SerializerError::UnsupportedContentType(
279 content_type.to_string(),
280 )),
281 }
282 }
283
284 pub fn serialize<T: Serialize>(&self, value: &T) -> SerializerResult<Vec<u8>> {
286 match self {
287 SerializerType::Json => JsonSerializer.serialize(value),
288 #[cfg(feature = "msgpack")]
289 SerializerType::MessagePack => MessagePackSerializer.serialize(value),
290 #[cfg(feature = "yaml")]
291 SerializerType::Yaml => YamlSerializer.serialize(value),
292 #[cfg(feature = "bson-format")]
293 SerializerType::Bson => BsonSerializer.serialize(value),
294 #[cfg(feature = "protobuf")]
295 SerializerType::Protobuf => Err(SerializerError::Serialize(
296 "Protobuf requires prost::Message; use ProtobufSerializer::serialize_message instead".to_string(),
297 )),
298 }
299 }
300
301 pub fn deserialize<T: DeserializeOwned>(&self, bytes: &[u8]) -> SerializerResult<T> {
303 match self {
304 SerializerType::Json => JsonSerializer.deserialize(bytes),
305 #[cfg(feature = "msgpack")]
306 SerializerType::MessagePack => MessagePackSerializer.deserialize(bytes),
307 #[cfg(feature = "yaml")]
308 SerializerType::Yaml => YamlSerializer.deserialize(bytes),
309 #[cfg(feature = "bson-format")]
310 SerializerType::Bson => BsonSerializer.deserialize(bytes),
311 #[cfg(feature = "protobuf")]
312 SerializerType::Protobuf => Err(SerializerError::Deserialize(
313 "Protobuf requires prost::Message; use ProtobufSerializer::deserialize_message instead".to_string(),
314 )),
315 }
316 }
317
318 #[inline]
320 pub fn content_type(&self) -> ContentType {
321 match self {
322 SerializerType::Json => JsonSerializer.content_type(),
323 #[cfg(feature = "msgpack")]
324 SerializerType::MessagePack => MessagePackSerializer.content_type(),
325 #[cfg(feature = "yaml")]
326 SerializerType::Yaml => YamlSerializer.content_type(),
327 #[cfg(feature = "bson-format")]
328 SerializerType::Bson => BsonSerializer.content_type(),
329 #[cfg(feature = "protobuf")]
330 SerializerType::Protobuf => ProtobufSerializer.content_type(),
331 }
332 }
333
334 #[inline]
336 pub fn content_encoding(&self) -> ContentEncoding {
337 match self {
338 SerializerType::Json => JsonSerializer.content_encoding(),
339 #[cfg(feature = "msgpack")]
340 SerializerType::MessagePack => MessagePackSerializer.content_encoding(),
341 #[cfg(feature = "yaml")]
342 SerializerType::Yaml => YamlSerializer.content_encoding(),
343 #[cfg(feature = "bson-format")]
344 SerializerType::Bson => BsonSerializer.content_encoding(),
345 #[cfg(feature = "protobuf")]
346 SerializerType::Protobuf => ProtobufSerializer.content_encoding(),
347 }
348 }
349
350 #[inline]
352 pub fn name(&self) -> &'static str {
353 match self {
354 SerializerType::Json => JsonSerializer.name(),
355 #[cfg(feature = "msgpack")]
356 SerializerType::MessagePack => MessagePackSerializer.name(),
357 #[cfg(feature = "yaml")]
358 SerializerType::Yaml => YamlSerializer.name(),
359 #[cfg(feature = "bson-format")]
360 SerializerType::Bson => BsonSerializer.name(),
361 #[cfg(feature = "protobuf")]
362 SerializerType::Protobuf => ProtobufSerializer.name(),
363 }
364 }
365}
366
367impl fmt::Display for SerializerType {
368 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369 write!(f, "{}", self.name())
370 }
371}
372
373impl TryFrom<&str> for SerializerType {
374 type Error = SerializerError;
375
376 fn try_from(content_type: &str) -> Result<Self, Self::Error> {
377 Self::from_content_type(content_type)
378 }
379}
380
381pub fn get_serializer(content_type: &str) -> SerializerResult<SerializerType> {
393 SerializerType::from_content_type(content_type)
394}
395
396pub struct SerializerRegistry {
398 default: SerializerType,
399}
400
401impl Default for SerializerRegistry {
402 fn default() -> Self {
403 Self::new()
404 }
405}
406
407impl SerializerRegistry {
408 pub fn new() -> Self {
410 Self {
411 default: SerializerType::Json,
412 }
413 }
414
415 #[inline]
417 pub fn default_serializer(&self) -> SerializerType {
418 self.default
419 }
420
421 pub fn get(&self, content_type: &str) -> SerializerResult<SerializerType> {
423 get_serializer(content_type)
424 }
425
426 pub fn available() -> Vec<&'static str> {
428 vec![
429 "application/json",
430 #[cfg(feature = "msgpack")]
431 "application/x-msgpack",
432 #[cfg(feature = "yaml")]
433 "application/x-yaml",
434 #[cfg(feature = "bson-format")]
435 "application/bson",
436 #[cfg(feature = "protobuf")]
437 "application/protobuf",
438 ]
439 }
440
441 pub fn detect_format(data: &[u8]) -> Option<SerializerType> {
452 if data.is_empty() {
453 return None;
454 }
455
456 let trimmed = data.iter().position(|&b| !b.is_ascii_whitespace());
458 if let Some(pos) = trimmed {
459 if data[pos] == b'{' || data[pos] == b'[' {
460 return Some(SerializerType::Json);
461 }
462 }
463
464 #[cfg(feature = "yaml")]
466 if data.starts_with(b"---") {
467 return Some(SerializerType::Yaml);
468 }
469
470 #[cfg(feature = "bson-format")]
472 if data.len() >= 5 {
473 let size = u32::from_le_bytes([data[0], data[1], data[2], data[3]]) as usize;
474 if size == data.len() && data[data.len() - 1] == 0x00 {
475 return Some(SerializerType::Bson);
476 }
477 }
478
479 #[cfg(feature = "msgpack")]
482 if matches!(
483 data[0],
484 0x80..=0x9f | 0xc0..=0xd3 | 0xd4..=0xd8 | 0xd9..=0xdf
485 ) {
486 if data[0] != b'{' && data[0] != b'[' {
488 return Some(SerializerType::MessagePack);
489 }
490 }
491
492 #[cfg(feature = "protobuf")]
498 if data.len() >= 2 {
499 let first = data[0];
500 let wire_type = first & 0x07;
501 let field_number = first >> 3;
502 if wire_type <= 5
503 && field_number > 0
504 && field_number < 100
505 && !first.is_ascii_whitespace()
506 && !first.is_ascii_alphanumeric()
507 && first != b'_'
508 && first != b'-'
509 {
510 return Some(SerializerType::Protobuf);
511 }
512 }
513
514 None
515 }
516
517 pub fn negotiate(
523 local_preferred: &[SerializerType],
524 remote_supported: &[SerializerType],
525 ) -> Option<SerializerType> {
526 local_preferred
527 .iter()
528 .find(|s| remote_supported.contains(s))
529 .copied()
530 }
531
532 pub fn available_types() -> Vec<SerializerType> {
537 #[allow(unused_mut)]
538 let mut types = vec![SerializerType::Json]; #[cfg(feature = "msgpack")]
541 types.push(SerializerType::MessagePack);
542
543 #[cfg(feature = "yaml")]
544 types.push(SerializerType::Yaml);
545
546 #[cfg(feature = "bson-format")]
547 types.push(SerializerType::Bson);
548
549 #[cfg(feature = "protobuf")]
550 types.push(SerializerType::Protobuf);
551
552 types
553 }
554}
555
556#[cfg(test)]
557mod tests {
558 use super::*;
559 use serde::{Deserialize, Serialize};
560
561 #[derive(Debug, PartialEq, Serialize, Deserialize)]
562 struct TestData {
563 name: String,
564 value: i32,
565 }
566
567 #[test]
568 fn test_json_serializer_round_trip() {
569 let serializer = JsonSerializer;
570 let data = TestData {
571 name: "test".to_string(),
572 value: 42,
573 };
574
575 let bytes = serializer.serialize(&data).unwrap();
576 let decoded: TestData = serializer.deserialize(&bytes).unwrap();
577
578 assert_eq!(data, decoded);
579 }
580
581 #[test]
582 fn test_json_serializer_content_type() {
583 let serializer = JsonSerializer;
584 assert_eq!(serializer.content_type(), ContentType::Json);
585 assert_eq!(serializer.content_encoding(), ContentEncoding::Utf8);
586 assert_eq!(serializer.name(), "json");
587 }
588
589 #[cfg(feature = "msgpack")]
590 #[test]
591 fn test_msgpack_serializer_round_trip() {
592 let serializer = MessagePackSerializer;
593 let data = TestData {
594 name: "msgpack_test".to_string(),
595 value: 100,
596 };
597
598 let bytes = serializer.serialize(&data).unwrap();
599 let decoded: TestData = serializer.deserialize(&bytes).unwrap();
600
601 assert_eq!(data, decoded);
602 }
603
604 #[cfg(feature = "msgpack")]
605 #[test]
606 fn test_msgpack_serializer_content_type() {
607 let serializer = MessagePackSerializer;
608 assert_eq!(serializer.content_type(), ContentType::MessagePack);
609 assert_eq!(serializer.content_encoding(), ContentEncoding::Binary);
610 assert_eq!(serializer.name(), "msgpack");
611 }
612
613 #[test]
614 fn test_get_serializer_json() {
615 let serializer = get_serializer("application/json").unwrap();
616 assert_eq!(serializer.name(), "json");
617 }
618
619 #[cfg(feature = "msgpack")]
620 #[test]
621 fn test_get_serializer_msgpack() {
622 let serializer = get_serializer("application/x-msgpack").unwrap();
623 assert_eq!(serializer.name(), "msgpack");
624 }
625
626 #[test]
627 fn test_get_serializer_unsupported() {
628 let result = get_serializer("application/unsupported");
629 assert!(result.is_err());
630 match result {
631 Err(SerializerError::UnsupportedContentType(ct)) => {
632 assert_eq!(ct, "application/unsupported");
633 }
634 _ => panic!("Expected UnsupportedContentType error"),
635 }
636 }
637
638 #[test]
639 fn test_serializer_registry() {
640 let registry = SerializerRegistry::new();
641 assert_eq!(registry.default_serializer().name(), "json");
642
643 let json = registry.get("application/json").unwrap();
644 assert_eq!(json.name(), "json");
645 }
646
647 #[test]
648 fn test_serializer_registry_available() {
649 let available = SerializerRegistry::available();
650 assert!(available.contains(&"application/json"));
651 }
652
653 #[test]
654 fn test_serializer_error_display() {
655 let err = SerializerError::Serialize("test error".to_string());
656 assert_eq!(err.to_string(), "Serialization error: test error");
657
658 let err = SerializerError::Deserialize("parse failed".to_string());
659 assert_eq!(err.to_string(), "Deserialization error: parse failed");
660
661 let err = SerializerError::UnsupportedContentType("text/plain".to_string());
662 assert_eq!(err.to_string(), "Unsupported content type: text/plain");
663
664 let err = SerializerError::Compression("gzip failed".to_string());
665 assert_eq!(err.to_string(), "Compression error: gzip failed");
666 }
667
668 #[cfg(feature = "bson-format")]
669 #[test]
670 fn test_bson_serializer_round_trip() {
671 let serializer = BsonSerializer;
672 let data = TestData {
673 name: "bson_test".to_string(),
674 value: 200,
675 };
676
677 let bytes = serializer.serialize(&data).unwrap();
678 let decoded: TestData = serializer.deserialize(&bytes).unwrap();
679
680 assert_eq!(data, decoded);
681 }
682
683 #[cfg(feature = "bson-format")]
684 #[test]
685 fn test_bson_serializer_content_type() {
686 let serializer = BsonSerializer;
687 assert_eq!(
688 serializer.content_type(),
689 ContentType::Custom("application/bson".to_string())
690 );
691 assert_eq!(serializer.content_encoding(), ContentEncoding::Binary);
692 assert_eq!(serializer.name(), "bson");
693 }
694
695 #[cfg(feature = "bson-format")]
696 #[test]
697 fn test_get_serializer_bson() {
698 let serializer = get_serializer("application/bson").unwrap();
699 assert_eq!(serializer.name(), "bson");
700 }
701
702 #[test]
703 fn test_serializer_type_equality() {
704 let json1 = SerializerType::Json;
705 let json2 = SerializerType::Json;
706 assert_eq!(json1, json2);
707
708 #[cfg(feature = "msgpack")]
709 {
710 let msgpack = SerializerType::MessagePack;
711 assert_ne!(json1, msgpack);
712 }
713 }
714
715 #[test]
716 fn test_serializer_type_hash() {
717 use std::collections::HashSet;
718
719 let mut set = HashSet::new();
720 set.insert(SerializerType::Json);
721 set.insert(SerializerType::Json); #[cfg(feature = "msgpack")]
724 set.insert(SerializerType::MessagePack);
725
726 #[cfg(feature = "msgpack")]
727 assert_eq!(set.len(), 2);
728
729 #[cfg(not(feature = "msgpack"))]
730 assert_eq!(set.len(), 1);
731
732 assert!(set.contains(&SerializerType::Json));
733 }
734
735 #[test]
736 fn test_serializer_type_display() {
737 assert_eq!(SerializerType::Json.to_string(), "json");
738
739 #[cfg(feature = "msgpack")]
740 assert_eq!(SerializerType::MessagePack.to_string(), "msgpack");
741
742 #[cfg(feature = "yaml")]
743 assert_eq!(SerializerType::Yaml.to_string(), "yaml");
744
745 #[cfg(feature = "bson-format")]
746 assert_eq!(SerializerType::Bson.to_string(), "bson");
747 }
748
749 #[test]
750 fn test_serializer_type_try_from() {
751 use std::convert::TryFrom;
752
753 let json = SerializerType::try_from("application/json").unwrap();
754 assert_eq!(json, SerializerType::Json);
755
756 #[cfg(feature = "msgpack")]
757 {
758 let msgpack = SerializerType::try_from("application/x-msgpack").unwrap();
759 assert_eq!(msgpack, SerializerType::MessagePack);
760 }
761
762 #[cfg(feature = "yaml")]
763 {
764 let yaml = SerializerType::try_from("application/yaml").unwrap();
765 assert_eq!(yaml, SerializerType::Yaml);
766 }
767
768 let result = SerializerType::try_from("application/unsupported");
770 assert!(result.is_err());
771 }
772
773 #[test]
774 fn test_serializer_type_default() {
775 let default_type = SerializerType::default();
776 assert_eq!(default_type, SerializerType::Json);
777 }
778
779 #[test]
780 fn test_serializer_type_copy() {
781 let json = SerializerType::Json;
782 let json_copy = json; let _json_original = json; assert_eq!(json_copy, SerializerType::Json);
786 }
787
788 #[test]
791 fn test_detect_format_empty_data() {
792 assert!(SerializerRegistry::detect_format(&[]).is_none());
793 }
794
795 #[test]
796 fn test_detect_format_json_object() {
797 let data = br#"{"key": "value"}"#;
798 assert_eq!(
799 SerializerRegistry::detect_format(data),
800 Some(SerializerType::Json)
801 );
802 }
803
804 #[test]
805 fn test_detect_format_json_array() {
806 let data = b"[1,2,3]";
807 assert_eq!(
808 SerializerRegistry::detect_format(data),
809 Some(SerializerType::Json)
810 );
811 }
812
813 #[test]
814 fn test_detect_format_json_with_leading_whitespace() {
815 let data = b" \t\n {\"key\": \"value\"}";
816 assert_eq!(
817 SerializerRegistry::detect_format(data),
818 Some(SerializerType::Json)
819 );
820 }
821
822 #[test]
823 fn test_detect_format_json_array_with_whitespace() {
824 let data = b" [1, 2, 3]";
825 assert_eq!(
826 SerializerRegistry::detect_format(data),
827 Some(SerializerType::Json)
828 );
829 }
830
831 #[cfg(feature = "msgpack")]
832 #[test]
833 fn test_detect_format_msgpack() {
834 use std::collections::HashMap;
835
836 let mut map = HashMap::new();
837 map.insert("key", "value");
838 let bytes = rmp_serde::to_vec(&map).expect("msgpack serialization failed");
839 assert_eq!(
840 SerializerRegistry::detect_format(&bytes),
841 Some(SerializerType::MessagePack)
842 );
843 }
844
845 #[cfg(feature = "msgpack")]
846 #[test]
847 fn test_detect_format_msgpack_fixmap() {
848 let data: &[u8] = &[
850 0x81, 0xa3, b'k', b'e', b'y', 0xa5, b'v', b'a', b'l', b'u', b'e',
851 ];
852 assert_eq!(
853 SerializerRegistry::detect_format(data),
854 Some(SerializerType::MessagePack)
855 );
856 }
857
858 #[cfg(feature = "bson-format")]
859 #[test]
860 fn test_detect_format_bson() {
861 let data = TestData {
862 name: "bson_detect".to_string(),
863 value: 42,
864 };
865 let bytes = bson::serialize_to_vec(&data).expect("bson serialization failed");
866 assert_eq!(
867 SerializerRegistry::detect_format(&bytes),
868 Some(SerializerType::Bson)
869 );
870 }
871
872 #[cfg(feature = "bson-format")]
873 #[test]
874 fn test_detect_format_bson_not_matching_size() {
875 let data: &[u8] = &[100, 0, 0, 0, 0x00];
877 assert_ne!(
878 SerializerRegistry::detect_format(data),
879 Some(SerializerType::Bson)
880 );
881 }
882
883 #[cfg(feature = "yaml")]
884 #[test]
885 fn test_detect_format_yaml() {
886 let data = b"---\nkey: value\n";
887 assert_eq!(
888 SerializerRegistry::detect_format(data),
889 Some(SerializerType::Yaml)
890 );
891 }
892
893 #[cfg(feature = "yaml")]
894 #[test]
895 fn test_detect_format_yaml_minimal() {
896 let data = b"---";
897 assert_eq!(
898 SerializerRegistry::detect_format(data),
899 Some(SerializerType::Yaml)
900 );
901 }
902
903 #[test]
904 fn test_detect_format_unknown_binary() {
905 let data: &[u8] = &[0x00, 0x00, 0x00];
907 assert!(SerializerRegistry::detect_format(data).is_none());
910 }
911
912 #[test]
913 fn test_detect_format_whitespace_only() {
914 let data = b" \t\n ";
915 assert!(SerializerRegistry::detect_format(data).is_none());
917 }
918
919 #[test]
922 fn test_negotiate_overlap() {
923 let local = [SerializerType::Json];
924 let remote = [SerializerType::Json];
925 assert_eq!(
926 SerializerRegistry::negotiate(&local, &remote),
927 Some(SerializerType::Json)
928 );
929 }
930
931 #[test]
932 fn test_negotiate_prefers_local_order() {
933 #[cfg(feature = "msgpack")]
934 {
935 let local = [SerializerType::MessagePack, SerializerType::Json];
936 let remote = [SerializerType::Json, SerializerType::MessagePack];
937 assert_eq!(
938 SerializerRegistry::negotiate(&local, &remote),
939 Some(SerializerType::MessagePack)
940 );
941 }
942 }
943
944 #[test]
945 fn test_negotiate_disjoint() {
946 let local = [SerializerType::Json];
948 let remote: &[SerializerType] = &[];
949 assert!(SerializerRegistry::negotiate(&local, remote).is_none());
950 }
951
952 #[test]
953 fn test_negotiate_empty_local() {
954 let local: &[SerializerType] = &[];
955 let remote = [SerializerType::Json];
956 assert!(SerializerRegistry::negotiate(local, &remote).is_none());
957 }
958
959 #[test]
960 fn test_negotiate_both_empty() {
961 let local: &[SerializerType] = &[];
962 let remote: &[SerializerType] = &[];
963 assert!(SerializerRegistry::negotiate(local, remote).is_none());
964 }
965
966 #[cfg(feature = "msgpack")]
967 #[test]
968 fn test_negotiate_partial_overlap() {
969 let local = [SerializerType::MessagePack, SerializerType::Json];
970 let remote = [SerializerType::Json];
971 assert_eq!(
972 SerializerRegistry::negotiate(&local, &remote),
973 Some(SerializerType::Json)
974 );
975 }
976
977 #[test]
980 fn test_available_types_always_has_json() {
981 let types = SerializerRegistry::available_types();
982 assert!(types.contains(&SerializerType::Json));
983 assert_eq!(types[0], SerializerType::Json);
985 }
986
987 #[cfg(feature = "msgpack")]
988 #[test]
989 fn test_available_types_has_msgpack() {
990 let types = SerializerRegistry::available_types();
991 assert!(types.contains(&SerializerType::MessagePack));
992 }
993
994 #[cfg(feature = "yaml")]
995 #[test]
996 fn test_available_types_has_yaml() {
997 let types = SerializerRegistry::available_types();
998 assert!(types.contains(&SerializerType::Yaml));
999 }
1000
1001 #[cfg(feature = "bson-format")]
1002 #[test]
1003 fn test_available_types_has_bson() {
1004 let types = SerializerRegistry::available_types();
1005 assert!(types.contains(&SerializerType::Bson));
1006 }
1007
1008 #[cfg(feature = "protobuf")]
1009 #[test]
1010 fn test_available_types_has_protobuf() {
1011 let types = SerializerRegistry::available_types();
1012 assert!(types.contains(&SerializerType::Protobuf));
1013 }
1014
1015 #[test]
1016 fn test_available_types_count() {
1017 let types = SerializerRegistry::available_types();
1018 let mut expected = 1; #[cfg(feature = "msgpack")]
1021 {
1022 expected += 1;
1023 }
1024 #[cfg(feature = "yaml")]
1025 {
1026 expected += 1;
1027 }
1028 #[cfg(feature = "bson-format")]
1029 {
1030 expected += 1;
1031 }
1032 #[cfg(feature = "protobuf")]
1033 {
1034 expected += 1;
1035 }
1036
1037 assert_eq!(types.len(), expected);
1038 }
1039
1040 #[cfg(feature = "protobuf")]
1041 #[test]
1042 fn test_serializer_type_protobuf_name() {
1043 assert_eq!(SerializerType::Protobuf.name(), "protobuf");
1044 }
1045
1046 #[cfg(feature = "protobuf")]
1047 #[test]
1048 fn test_serializer_type_protobuf_content_type() {
1049 assert_eq!(
1050 SerializerType::Protobuf.content_type(),
1051 ContentType::Custom("application/protobuf".to_string())
1052 );
1053 }
1054}