1#![warn(missing_docs)]
2use std::{collections::VecDeque, sync::atomic::Ordering};
12
13use bytes::Bytes;
14
15use serde::{Deserialize, Serialize};
16use socketioxide_core::{
17 Str, Value,
18 packet::{Packet, PacketData},
19 parser::{Parse, ParseError, ParserError, ParserState},
20};
21
22mod de;
23mod ser;
24mod value;
25
26#[derive(Debug, Default, Clone, Copy)]
29pub struct CommonParser;
30
31impl Parse for CommonParser {
32 fn encode(self, packet: Packet) -> Value {
33 ser::serialize_packet(packet)
34 }
35
36 fn decode_str(self, state: &ParserState, value: Str) -> Result<Packet, ParseError> {
37 let (packet, incoming_binary_cnt) = de::deserialize_packet(value)?;
38 if packet.inner.is_binary() {
39 let incoming_binary_cnt = incoming_binary_cnt.ok_or(ParseError::InvalidAttachments)?;
40 if !is_bin_packet_complete(&packet.inner, incoming_binary_cnt) {
41 *state.partial_bin_packet.lock().unwrap() = Some(packet);
42 state
43 .incoming_binary_cnt
44 .store(incoming_binary_cnt, Ordering::Release);
45 Err(ParseError::NeedsMoreBinaryData)
46 } else {
47 Ok(packet)
48 }
49 } else {
50 Ok(packet)
51 }
52 }
53
54 fn decode_bin(self, state: &ParserState, data: Bytes) -> Result<Packet, ParseError> {
55 let packet = &mut *state.partial_bin_packet.lock().unwrap();
56 match packet {
57 Some(Packet {
58 inner:
59 PacketData::BinaryEvent(Value::Str(_, binaries), _)
60 | PacketData::BinaryAck(Value::Str(_, binaries), _),
61 ..
62 }) => {
63 let binaries = binaries.get_or_insert(VecDeque::new());
64 binaries.push_back(Bytes::copy_from_slice(&data));
67 if state.incoming_binary_cnt.load(Ordering::Relaxed) > binaries.len() {
68 Err(ParseError::NeedsMoreBinaryData)
69 } else {
70 Ok(packet.take().unwrap())
71 }
72 }
73 _ => Err(ParseError::UnexpectedBinaryPacket),
74 }
75 }
76
77 #[inline]
78 fn encode_value<T: ?Sized + Serialize>(
79 self,
80 data: &T,
81 event: Option<&str>,
82 ) -> Result<Value, ParserError> {
83 value::to_value(data, event).map_err(ParserError::new)
84 }
85
86 #[inline]
87 fn decode_value<'de, T: Deserialize<'de>>(
88 self,
89 value: &'de mut Value,
90 with_event: bool,
91 ) -> Result<T, ParserError> {
92 value::from_value(value, with_event).map_err(ParserError::new)
93 }
94
95 fn decode_default<'de, T: Deserialize<'de>>(
96 self,
97 value: Option<&'de Value>,
98 ) -> Result<T, ParserError> {
99 if let Some(value) = value {
100 let data = value
101 .as_str()
102 .expect("CommonParser only supports string values");
103 serde_json::from_str(data).map_err(ParserError::new)
104 } else {
105 serde_json::from_str("{}").map_err(ParserError::new)
106 }
107 }
108
109 fn encode_default<T: ?Sized + Serialize>(self, data: &T) -> Result<Value, ParserError> {
110 let value = serde_json::to_string(data).map_err(ParserError::new)?;
111 Ok(Value::Str(Str::from(value), None))
112 }
113
114 #[inline]
115 fn read_event(self, value: &Value) -> Result<&str, ParserError> {
116 value::read_event(value).map_err(ParserError::new)
117 }
118}
119
120fn is_bin_packet_complete(packet: &PacketData, incoming_binary_cnt: usize) -> bool {
122 match &packet {
123 PacketData::BinaryEvent(Value::Str(_, binaries), _)
124 | PacketData::BinaryAck(Value::Str(_, binaries), _) => {
125 incoming_binary_cnt == binaries.as_ref().map(VecDeque::len).unwrap_or(0)
126 }
127 _ => true,
128 }
129}
130
131#[cfg(test)]
132mod test {
133 use std::collections::HashMap;
134
135 use crate::is_bin_packet_complete;
136
137 use super::*;
138 use serde_json::json;
139 use socketioxide_core::{Sid, packet::ConnectPacket};
140
141 fn to_event_value(data: &impl serde::Serialize, event: &str) -> Value {
142 CommonParser.encode_value(data, Some(event)).unwrap()
143 }
144
145 fn to_value(data: &impl serde::Serialize) -> Value {
146 CommonParser.encode_value(data, None).unwrap()
147 }
148 fn to_connect_value(data: &impl serde::Serialize) -> Value {
149 Value::Str(Str::from(serde_json::to_string(data).unwrap()), None)
150 }
151 fn encode(packet: Packet) -> String {
152 match CommonParser.encode(packet) {
153 Value::Str(d, _) => d.into(),
154 Value::Bytes(_) => panic!("testing only returns str"),
155 }
156 }
157 fn decode(value: String) -> Packet {
158 CommonParser
159 .decode_str(&Default::default(), value.into())
160 .unwrap()
161 }
162
163 #[test]
164 fn packet_decode_connect() {
165 let sid = Sid::new();
166 let payload = format!("0{}", json!({ "sid": sid }));
167 let packet = decode(payload);
168 let value = to_connect_value(&ConnectPacket { sid });
169 assert_eq!(Packet::connect("/", Some(value.clone())), packet);
170
171 let payload = format!("0/admin™,{}", json!({ "sid": sid }));
172 let packet = decode(payload);
173 assert_eq!(Packet::connect("/admin™", Some(value)), packet);
174 }
175
176 #[test]
177 fn packet_encode_connect() {
178 let sid = Sid::new();
179 let value = to_connect_value(&ConnectPacket { sid });
180 let payload = format!("0{}", json!({ "sid": sid }));
181 let packet = encode(Packet::connect("/", Some(value.clone())));
182 assert_eq!(packet, payload);
183
184 let payload = format!("0/admin™,{}", json!({ "sid": sid }));
185 let packet: String = encode(Packet::connect("/admin™", Some(value)));
186 assert_eq!(packet, payload);
187 }
188
189 #[test]
192 fn packet_decode_disconnect() {
193 let payload = "1".to_string();
194 let packet = decode(payload);
195 assert_eq!(Packet::disconnect("/"), packet);
196
197 let payload = "1/admin™,".to_string();
198 let packet = decode(payload);
199 assert_eq!(Packet::disconnect("/admin™"), packet);
200 }
201
202 #[test]
203 fn packet_encode_disconnect() {
204 let payload = "1".to_string();
205 let packet = encode(Packet::disconnect("/"));
206 assert_eq!(packet, payload);
207
208 let payload = "1/admin™,".to_string();
209 let packet = encode(Packet::disconnect("/admin™"));
210 assert_eq!(packet, payload);
211 }
212
213 #[test]
215 fn packet_decode_event() {
216 let payload = format!("2{}", json!(["event", { "data": "value" }]));
217 let packet = decode(payload);
218
219 assert_eq!(
220 Packet::event("/", to_event_value(&json!({"data": "value"}), "event")),
221 packet
222 );
223
224 let payload = format!("21{}", json!(["event", { "data": "value" }]));
226 let packet = decode(payload);
227
228 let mut comparison_packet =
229 Packet::event("/", to_event_value(&json!({"data": "value"}), "event"));
230 comparison_packet.inner.set_ack_id(1);
231 assert_eq!(packet, comparison_packet);
232
233 let payload = format!("2/admin™,{}", json!(["event", { "data": "value™" }]));
235 let packet = decode(payload);
236
237 assert_eq!(
238 Packet::event(
239 "/admin™",
240 to_event_value(&json!({"data": "value™"}), "event")
241 ),
242 packet
243 );
244
245 let payload = format!("2/admin™,1{}", json!(["event", { "data": "value™" }]));
247 let mut packet = decode(payload);
248 packet.inner.set_ack_id(1);
249
250 let mut comparison_packet = Packet::event(
251 "/admin™",
252 to_event_value(&json!({"data": "value™"}), "event"),
253 );
254 comparison_packet.inner.set_ack_id(1);
255
256 assert_eq!(packet, comparison_packet);
257 }
258
259 #[test]
260 fn packet_encode_event() {
261 let payload = format!("2{}", json!(["event", { "data": "value™" }]));
262 let packet = encode(Packet::event(
263 "/",
264 to_event_value(&json!({ "data": "value™" }), "event"),
265 ));
266
267 assert_eq!(packet, payload);
268
269 let payload = format!("2{}", json!(["event", []]));
271 let packet = encode(Packet::event("/", to_event_value(&json!([]), "event")));
272
273 assert_eq!(packet, payload);
274
275 let payload = format!("21{}", json!(["event", { "data": "value™" }]));
277 let mut packet = Packet::event("/", to_event_value(&json!({ "data": "value™" }), "event"));
278 packet.inner.set_ack_id(1);
279 let packet = encode(packet);
280
281 assert_eq!(packet, payload);
282
283 let payload = format!("2/admin™,{}", json!(["event", { "data": "value™" }]));
285 let packet = encode(Packet::event(
286 "/admin™",
287 to_event_value(&json!({"data": "value™"}), "event"),
288 ));
289
290 assert_eq!(packet, payload);
291
292 let payload = format!("2/admin™,1{}", json!(["event", { "data": "value™" }]));
294 let mut packet = Packet::event(
295 "/admin™",
296 to_event_value(&json!({"data": "value™"}), "event"),
297 );
298 packet.inner.set_ack_id(1);
299 let packet = encode(packet);
300 assert_eq!(packet, payload);
301 }
302
303 #[test]
305 fn packet_decode_event_ack() {
306 let payload = "354[\"data\"]".to_string();
307 let packet = decode(payload);
308
309 assert_eq!(Packet::ack("/", to_value(&json!("data")), 54), packet);
310
311 let payload = "3/admin™,54[\"data\"]".to_string();
312 let packet = decode(payload);
313
314 assert_eq!(Packet::ack("/admin™", to_value(&json!("data")), 54), packet);
315 }
316
317 #[test]
318 fn packet_encode_event_ack() {
319 let payload = "354[\"data\"]".to_string();
320 let packet = encode(Packet::ack("/", to_value(&json!("data")), 54));
321 assert_eq!(packet, payload);
322
323 let payload = "3/admin™,54[\"data\"]".to_string();
324 let packet = encode(Packet::ack("/admin™", to_value(&json!("data")), 54));
325 assert_eq!(packet, payload);
326 }
327
328 #[test]
329 fn packet_encode_connect_error() {
330 let payload = format!("4{}", json!({ "message": "Invalid namespace" }));
331 let packet = encode(Packet::connect_error("/", "Invalid namespace"));
332 assert_eq!(packet, payload);
333
334 let payload = format!("4/admin™,{}", json!({ "message": "Invalid namespace" }));
335 let packet = encode(Packet::connect_error("/admin™", "Invalid namespace"));
336 assert_eq!(packet, payload);
337 }
338
339 #[test]
341 fn packet_encode_binary_event() {
342 let json = json!(["event", { "data": "value™" }, { "_placeholder": true, "num": 0}]);
343
344 let payload = format!("51-{json}");
345 let packet = encode(Packet::event(
346 "/",
347 to_event_value(
348 &(json!({ "data": "value™" }), Bytes::from_static(&[1])),
349 "event",
350 ),
351 ));
352
353 assert_eq!(packet, payload);
354
355 let payload = format!("51-254{json}");
357 let mut packet = Packet::event(
358 "/",
359 to_event_value(
360 &(json!({ "data": "value™" }), Bytes::from_static(&[1])),
361 "event",
362 ),
363 );
364 packet.inner.set_ack_id(254);
365 let packet = encode(packet);
366
367 assert_eq!(packet, payload);
368
369 let payload = format!("51-/admin™,{json}");
371 let packet = encode(Packet::event(
372 "/admin™",
373 to_event_value(
374 &(json!({ "data": "value™" }), Bytes::from_static(&[1])),
375 "event",
376 ),
377 ));
378
379 assert_eq!(packet, payload);
380
381 let payload = format!("51-/admin™,254{json}");
383 let mut packet = Packet::event(
384 "/admin™",
385 to_event_value(
386 &(json!({ "data": "value™" }), Bytes::from_static(&[1])),
387 "event",
388 ),
389 );
390 packet.inner.set_ack_id(254);
391 let packet = encode(packet);
392 assert_eq!(packet, payload);
393 }
394
395 #[test]
396 fn packet_decode_binary_event() {
397 let json = json!(["event", { "data": "value™" },{ "_placeholder": true, "num": 0},{ "_placeholder": true, "num": 1}]);
398 let comparison_packet = |ack, ns: &'static str| {
399 let data = to_event_value(
400 &(
401 json!({"data": "value™"}),
402 Bytes::from_static(&[1]),
403 Bytes::from_static(&[2]),
404 ),
405 "event",
406 );
407 Packet {
408 inner: PacketData::BinaryEvent(data, ack),
409 ns: ns.into(),
410 }
411 };
412 let state = ParserState::default();
413 let payload = format!("52-{json}");
414 assert!(matches!(
415 CommonParser.decode_str(&state, payload.into()),
416 Err(ParseError::NeedsMoreBinaryData)
417 ));
418 assert!(matches!(
419 CommonParser.decode_bin(&state, Bytes::from_static(&[1])),
420 Err(ParseError::NeedsMoreBinaryData)
421 ));
422 let packet = CommonParser
423 .decode_bin(&state, Bytes::from_static(&[2]))
424 .unwrap();
425
426 assert_eq!(packet, comparison_packet(None, "/"));
427
428 let state = ParserState::default();
430 let payload = format!("52-254{json}");
431 assert!(matches!(
432 CommonParser.decode_str(&state, payload.into()),
433 Err(ParseError::NeedsMoreBinaryData)
434 ));
435 assert!(matches!(
436 CommonParser.decode_bin(&state, Bytes::from_static(&[1])),
437 Err(ParseError::NeedsMoreBinaryData)
438 ));
439 let packet = CommonParser
440 .decode_bin(&state, Bytes::from_static(&[2]))
441 .unwrap();
442
443 assert_eq!(packet, comparison_packet(Some(254), "/"));
444
445 let state = ParserState::default();
447 let payload = format!("52-/admin™,{json}");
448 assert!(matches!(
449 CommonParser.decode_str(&state, payload.into()),
450 Err(ParseError::NeedsMoreBinaryData)
451 ));
452 assert!(matches!(
453 CommonParser.decode_bin(&state, Bytes::from_static(&[1])),
454 Err(ParseError::NeedsMoreBinaryData)
455 ));
456 let packet = CommonParser
457 .decode_bin(&state, Bytes::from_static(&[2]))
458 .unwrap();
459
460 assert_eq!(packet, comparison_packet(None, "/admin™"));
461
462 let state = ParserState::default();
464 let payload = format!("52-/admin™,254{json}");
465 assert!(matches!(
466 CommonParser.decode_str(&state, payload.into()),
467 Err(ParseError::NeedsMoreBinaryData)
468 ));
469 assert!(matches!(
470 CommonParser.decode_bin(&state, Bytes::from_static(&[1])),
471 Err(ParseError::NeedsMoreBinaryData)
472 ));
473 let packet = CommonParser
474 .decode_bin(&state, Bytes::from_static(&[2]))
475 .unwrap();
476
477 assert_eq!(packet, comparison_packet(Some(254), "/admin™"));
478 }
479
480 #[test]
482 fn packet_encode_binary_ack() {
483 let json = json!([{ "data": "value™" }, { "_placeholder": true, "num": 0}]);
484
485 let payload = format!("61-54{json}");
486 let packet = encode(Packet::ack(
487 "/",
488 to_value(&(json!({ "data": "value™" }), Bytes::from_static(&[1]))),
489 54,
490 ));
491
492 assert_eq!(packet, payload);
493
494 let payload = format!("61-/admin™,54{json}");
496 let packet = encode(Packet::ack(
497 "/admin™",
498 to_value(&(json!({ "data": "value™" }), Bytes::from_static(&[1]))),
499 54,
500 ));
501
502 assert_eq!(packet, payload);
503 }
504
505 #[test]
506 fn packet_decode_binary_ack() {
507 let json = json!([{ "data": "value™" }, { "_placeholder": true, "num": 0}]);
508 let comparison_packet = |ack, ns: &'static str| Packet {
509 inner: PacketData::BinaryAck(
510 to_value(&(json!({ "data": "value™" }), Bytes::from_static(&[1]))),
511 ack,
512 ),
513 ns: ns.into(),
514 };
515
516 let payload = format!("61-54{json}");
517 let state = ParserState::default();
518 assert!(matches!(
519 CommonParser.decode_str(&state, payload.into()),
520 Err(ParseError::NeedsMoreBinaryData)
521 ));
522 let packet = CommonParser
523 .decode_bin(&state, Bytes::from_static(&[1]))
524 .unwrap();
525
526 assert_eq!(packet, comparison_packet(54, "/"));
527
528 let state = ParserState::default();
530 let payload = format!("61-/admin™,54{json}");
531 assert!(matches!(
532 CommonParser.decode_str(&state, payload.into()),
533 Err(ParseError::NeedsMoreBinaryData)
534 ));
535 let packet = CommonParser
536 .decode_bin(&state, Bytes::from_static(&[1]))
537 .unwrap();
538 assert_eq!(packet, comparison_packet(54, "/admin™"));
539 }
540
541 #[test]
542 fn packet_reject_invalid_binary_event() {
543 let payload = "5invalid".to_owned();
544 let err = CommonParser
545 .decode_str(&Default::default(), payload.into())
546 .unwrap_err();
547
548 assert!(matches!(err, ParseError::InvalidAttachments));
549 }
550
551 #[test]
552 fn decode_default_none() {
553 let data = CommonParser.decode_default::<HashMap<String, ()>>(None);
556 assert!(matches!(data, Ok(d) if d.is_empty()));
557 }
558
559 #[test]
560 fn decode_default_some() {
561 let data =
564 CommonParser.decode_default::<String>(Some(&Value::Str("\"test\"".into(), None)));
565 assert!(matches!(data, Ok(d) if d == "test"));
566 }
567
568 #[test]
569 fn encode_default() {
570 let data = CommonParser.encode_default(&20);
571 assert!(matches!(data, Ok(Value::Str(d, None)) if d == "20"));
572 }
573
574 #[test]
575 fn read_event() {
576 let data = Value::Str(r#"["event",{"data":1,"complex":[132,12]}]"#.into(), None);
577 let event = CommonParser.read_event(&data).unwrap();
578 assert_eq!(event, "event");
579 }
580
581 #[test]
582 fn unexpected_bin_packet() {
583 let err = CommonParser.decode_bin(&Default::default(), Bytes::new());
584 assert!(matches!(err, Err(ParseError::UnexpectedBinaryPacket)));
585 }
586 #[test]
587 fn check_is_bin_packet_complete() {
588 let data = PacketData::BinaryEvent(Value::Str("".into(), Some(vec![].into())), None);
589 assert!(!is_bin_packet_complete(&data, 2));
590 assert!(is_bin_packet_complete(&data, 0));
591 let data =
592 PacketData::BinaryAck(Value::Str("".into(), Some(vec![Bytes::new()].into())), 12);
593 assert!(is_bin_packet_complete(&data, 1));
594 assert!(!is_bin_packet_complete(&data, 2));
595
596 let data = PacketData::Connect(None);
598 assert!(is_bin_packet_complete(&data, 0));
599 assert!(is_bin_packet_complete(&data, 1));
600 }
601}