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