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