network_protocol/core/
serialization.rs1use serde::{Deserialize, Serialize};
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
36pub enum SerializationFormat {
37 #[default]
39 Bincode,
40 Json,
42 MessagePack,
44}
45
46impl SerializationFormat {
47 pub fn format_byte(self) -> u8 {
49 match self {
50 SerializationFormat::Bincode => 0x01,
51 SerializationFormat::Json => 0x02,
52 SerializationFormat::MessagePack => 0x03,
53 }
54 }
55
56 pub fn from_byte(byte: u8) -> Option<Self> {
58 match byte {
59 0x01 => Some(SerializationFormat::Bincode),
60 0x02 => Some(SerializationFormat::Json),
61 0x03 => Some(SerializationFormat::MessagePack),
62 _ => None,
63 }
64 }
65
66 pub fn name(self) -> &'static str {
68 match self {
69 SerializationFormat::Bincode => "Bincode",
70 SerializationFormat::Json => "JSON",
71 SerializationFormat::MessagePack => "MessagePack",
72 }
73 }
74}
75
76pub trait MultiFormat: Serialize + for<'de> Deserialize<'de> + Sized {
78 fn serialize_format(&self, format: SerializationFormat) -> crate::error::Result<Vec<u8>> {
80 match format {
81 SerializationFormat::Bincode => bincode::serialize(self)
82 .map_err(|e| crate::error::ProtocolError::SerializeError(e.to_string())),
83 SerializationFormat::Json => serde_json::to_vec(self)
84 .map_err(|e| crate::error::ProtocolError::SerializeError(e.to_string())),
85 SerializationFormat::MessagePack => rmp_serde::to_vec(self)
86 .map_err(|e| crate::error::ProtocolError::SerializeError(e.to_string())),
87 }
88 }
89
90 fn serialize_with_header(&self, format: SerializationFormat) -> crate::error::Result<Vec<u8>> {
92 let mut data = vec![format.format_byte()];
93 let mut payload = self.serialize_format(format)?;
94 data.append(&mut payload);
95 Ok(data)
96 }
97
98 fn deserialize_format(data: &[u8], format: SerializationFormat) -> crate::error::Result<Self> {
100 match format {
101 SerializationFormat::Bincode => bincode::deserialize(data)
102 .map_err(|e| crate::error::ProtocolError::DeserializeError(e.to_string())),
103 SerializationFormat::Json => serde_json::from_slice(data)
104 .map_err(|e| crate::error::ProtocolError::DeserializeError(e.to_string())),
105 SerializationFormat::MessagePack => rmp_serde::from_slice(data)
106 .map_err(|e| crate::error::ProtocolError::DeserializeError(e.to_string())),
107 }
108 }
109
110 fn deserialize_with_header(data: &[u8]) -> crate::error::Result<(Self, SerializationFormat)> {
112 if data.is_empty() {
113 return Err(crate::error::ProtocolError::DeserializeError(
114 "Empty data".to_string(),
115 ));
116 }
117
118 let format = SerializationFormat::from_byte(data[0]).ok_or_else(|| {
119 crate::error::ProtocolError::DeserializeError(format!(
120 "Unknown format byte: {}",
121 data[0]
122 ))
123 })?;
124
125 let value = Self::deserialize_format(&data[1..], format)?;
126 Ok((value, format))
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133 use crate::protocol::message::Message;
134
135 #[test]
136 #[allow(clippy::expect_used)]
137 fn test_format_byte_roundtrip() {
138 for format in &[
139 SerializationFormat::Bincode,
140 SerializationFormat::Json,
141 SerializationFormat::MessagePack,
142 ] {
143 let byte = format.format_byte();
144 let recovered = SerializationFormat::from_byte(byte).expect("valid format byte");
145 assert_eq!(*format, recovered);
146 }
147 }
148
149 #[test]
150 fn test_format_names() {
151 assert_eq!(SerializationFormat::Bincode.name(), "Bincode");
152 assert_eq!(SerializationFormat::Json.name(), "JSON");
153 assert_eq!(SerializationFormat::MessagePack.name(), "MessagePack");
154 }
155
156 #[test]
157 fn test_default_format() {
158 assert_eq!(SerializationFormat::default(), SerializationFormat::Bincode);
159 }
160
161 #[test]
162 #[allow(clippy::expect_used)]
163 fn test_bincode_serialization() {
164 let msg = Message::Ping;
165 let bytes = bincode::serialize(&msg).expect("serialize");
166 let recovered: Message = bincode::deserialize(&bytes).expect("deserialize");
167 assert_eq!(msg, recovered);
168 }
169
170 #[test]
171 #[allow(clippy::expect_used)]
172 fn test_json_serialization() {
173 let msg = Message::Ping;
174 let bytes = serde_json::to_vec(&msg).expect("serialize");
175 let recovered: Message = serde_json::from_slice(&bytes).expect("deserialize");
176 assert_eq!(msg, recovered);
177 }
178
179 #[test]
180 #[allow(clippy::expect_used)]
181 fn test_messagepack_serialization() {
182 let msg = Message::Ping;
183 let bytes = rmp_serde::to_vec(&msg).expect("serialize");
184 let recovered: Message = rmp_serde::from_slice(&bytes).expect("deserialize");
185 assert_eq!(msg, recovered);
186 }
187
188 #[test]
189 #[allow(clippy::expect_used)]
190 fn test_format_sizes() {
191 let msg = Message::Ping;
192
193 let bincode_size = bincode::serialize(&msg).expect("bincode").len();
194 let json_size = serde_json::to_vec(&msg).expect("json").len();
195 let msgpack_size = rmp_serde::to_vec(&msg).expect("msgpack").len();
196
197 println!("Bincode: {bincode_size} bytes");
198 println!("JSON: {json_size} bytes");
199 println!("MessagePack: {msgpack_size} bytes");
200
201 assert!(msgpack_size < json_size);
203 }
204}