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