wsio_core/packet/codecs/
mod.rs1use anyhow::Result;
2use serde::{
3 Serialize,
4 de::DeserializeOwned,
5};
6
7#[cfg(feature = "packet-codec-cbor")]
8mod cbor;
9
10#[cfg(feature = "packet-codec-msgpack")]
11mod msgpack;
12
13#[cfg(feature = "packet-codec-postcard")]
14mod postcard;
15
16mod serde_json;
17
18#[cfg(feature = "packet-codec-sonic-rs")]
19mod sonic_rs;
20
21#[cfg(feature = "packet-codec-cbor")]
22use self::cbor::WsIoPacketCborCodec;
23#[cfg(feature = "packet-codec-msgpack")]
24use self::msgpack::WsIoPacketMsgpackCodec;
25#[cfg(feature = "packet-codec-postcard")]
26use self::postcard::WsIoPacketPostcardCodec;
27use self::serde_json::WsIoPacketSerdeJsonCodec;
28#[cfg(feature = "packet-codec-sonic-rs")]
29use self::sonic_rs::WsIoPacketSonicRsCodec;
30use super::WsIoPacket;
31
32#[derive(Clone, Copy, Debug)]
34pub enum WsIoPacketCodec {
35 #[cfg(feature = "packet-codec-cbor")]
36 Cbor,
37
38 #[cfg(feature = "packet-codec-msgpack")]
39 Msgpack,
40
41 #[cfg(feature = "packet-codec-postcard")]
42 Postcard,
43
44 SerdeJson,
45
46 #[cfg(feature = "packet-codec-sonic-rs")]
47 SonicRs,
48}
49
50impl WsIoPacketCodec {
51 #[inline]
52 pub fn decode(&self, bytes: &[u8]) -> Result<WsIoPacket> {
53 match self {
54 #[cfg(feature = "packet-codec-cbor")]
55 Self::Cbor => WsIoPacketCborCodec.decode(bytes),
56
57 #[cfg(feature = "packet-codec-msgpack")]
58 Self::Msgpack => WsIoPacketMsgpackCodec.decode(bytes),
59
60 #[cfg(feature = "packet-codec-postcard")]
61 Self::Postcard => WsIoPacketPostcardCodec.decode(bytes),
62
63 Self::SerdeJson => WsIoPacketSerdeJsonCodec.decode(bytes),
64
65 #[cfg(feature = "packet-codec-sonic-rs")]
66 Self::SonicRs => WsIoPacketSonicRsCodec.decode(bytes),
67 }
68 }
69
70 #[inline]
71 pub fn decode_data<D: DeserializeOwned>(&self, bytes: &[u8]) -> Result<D> {
72 match self {
73 #[cfg(feature = "packet-codec-cbor")]
74 Self::Cbor => WsIoPacketCborCodec.decode_data(bytes),
75
76 #[cfg(feature = "packet-codec-msgpack")]
77 Self::Msgpack => WsIoPacketMsgpackCodec.decode_data(bytes),
78
79 #[cfg(feature = "packet-codec-postcard")]
80 Self::Postcard => WsIoPacketPostcardCodec.decode_data(bytes),
81
82 Self::SerdeJson => WsIoPacketSerdeJsonCodec.decode_data(bytes),
83
84 #[cfg(feature = "packet-codec-sonic-rs")]
85 Self::SonicRs => WsIoPacketSonicRsCodec.decode_data(bytes),
86 }
87 }
88
89 #[inline]
90 pub fn encode(&self, packet: &WsIoPacket) -> Result<Vec<u8>> {
91 match self {
92 #[cfg(feature = "packet-codec-cbor")]
93 Self::Cbor => WsIoPacketCborCodec.encode(packet),
94
95 #[cfg(feature = "packet-codec-msgpack")]
96 Self::Msgpack => WsIoPacketMsgpackCodec.encode(packet),
97
98 #[cfg(feature = "packet-codec-postcard")]
99 Self::Postcard => WsIoPacketPostcardCodec.encode(packet),
100
101 Self::SerdeJson => WsIoPacketSerdeJsonCodec.encode(packet),
102
103 #[cfg(feature = "packet-codec-sonic-rs")]
104 Self::SonicRs => WsIoPacketSonicRsCodec.encode(packet),
105 }
106 }
107
108 #[inline]
109 pub fn encode_data<D: Serialize>(&self, data: &D) -> Result<Vec<u8>> {
110 match self {
111 #[cfg(feature = "packet-codec-cbor")]
112 Self::Cbor => WsIoPacketCborCodec.encode_data(data),
113
114 #[cfg(feature = "packet-codec-msgpack")]
115 Self::Msgpack => WsIoPacketMsgpackCodec.encode_data(data),
116
117 #[cfg(feature = "packet-codec-postcard")]
118 Self::Postcard => WsIoPacketPostcardCodec.encode_data(data),
119
120 Self::SerdeJson => WsIoPacketSerdeJsonCodec.encode_data(data),
121
122 #[cfg(feature = "packet-codec-sonic-rs")]
123 Self::SonicRs => WsIoPacketSonicRsCodec.encode_data(data),
124 }
125 }
126
127 #[inline]
128 pub fn is_text(&self) -> bool {
129 match self {
130 #[cfg(feature = "packet-codec-cbor")]
131 Self::Cbor => WsIoPacketCborCodec::IS_TEXT,
132
133 #[cfg(feature = "packet-codec-msgpack")]
134 Self::Msgpack => WsIoPacketMsgpackCodec::IS_TEXT,
135
136 #[cfg(feature = "packet-codec-postcard")]
137 Self::Postcard => WsIoPacketPostcardCodec::IS_TEXT,
138
139 Self::SerdeJson => WsIoPacketSerdeJsonCodec::IS_TEXT,
140
141 #[cfg(feature = "packet-codec-sonic-rs")]
142 Self::SonicRs => WsIoPacketSonicRsCodec::IS_TEXT,
143 }
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use serde::{
150 Deserialize,
151 Serialize,
152 };
153
154 use super::*;
155 use crate::packet::{
156 WsIoPacket,
157 WsIoPacketType,
158 };
159
160 #[derive(Debug, Deserialize, PartialEq, Serialize)]
161 struct TestPayload {
162 id: u32,
163 message: String,
164 }
165
166 macro_rules! test_codec {
167 ($codec:expr, $name:ident) => {
168 #[test]
169 fn $name() {
170 let codec = $codec;
171
172 let original_data = TestPayload {
174 id: 42,
175 message: "hello world".to_string(),
176 };
177
178 let encoded_data = codec.encode_data(&original_data).expect("Failed to encode data");
179 let decoded_data: TestPayload = codec.decode_data(&encoded_data).expect("Failed to decode data");
180 assert_eq!(
181 original_data, decoded_data,
182 "Data decoding did not match original"
183 );
184
185 let packet = WsIoPacket::new_event("chat", Some(encoded_data.clone()));
187 let encoded_packet = codec.encode(&packet).expect("Failed to encode packet");
188 let decoded_packet = codec.decode(&encoded_packet).expect("Failed to decode packet");
189
190 assert!(
191 matches!(decoded_packet.r#type, WsIoPacketType::Event),
192 "Packet type mismatch"
193 );
194
195 assert_eq!(decoded_packet.key.as_deref(), Some("chat"), "Packet key mismatch");
196 assert_eq!(decoded_packet.data, Some(encoded_data), "Packet data mismatch");
197
198 let packet = WsIoPacket::new_disconnect();
200 let encoded_packet = codec.encode(&packet).expect("Failed to encode disconnect packet");
201 let decoded_packet = codec
202 .decode(&encoded_packet)
203 .expect("Failed to decode disconnect packet");
204
205 assert!(
206 matches!(decoded_packet.r#type, WsIoPacketType::Disconnect),
207 "Packet type mismatch"
208 );
209
210 assert_eq!(decoded_packet.key, None, "Packet key should be None");
211 assert_eq!(decoded_packet.data, None, "Packet data should be None");
212 }
213 };
214 }
215
216 #[cfg(feature = "packet-codec-cbor")]
217 test_codec!(WsIoPacketCodec::Cbor, test_cbor_codec);
218
219 #[cfg(feature = "packet-codec-msgpack")]
220 test_codec!(WsIoPacketCodec::Msgpack, test_msgpack_codec);
221
222 #[cfg(feature = "packet-codec-postcard")]
223 test_codec!(WsIoPacketCodec::Postcard, test_postcard_codec);
224
225 test_codec!(WsIoPacketCodec::SerdeJson, test_serde_json_codec);
226
227 #[cfg(feature = "packet-codec-sonic-rs")]
228 test_codec!(WsIoPacketCodec::SonicRs, test_sonic_rs_codec);
229}