Repository: 1c3t3a/rust-socketio (language: rust)

Issue:
Optimization possible when validating deserialization
https://github.com/1c3t3a/rust-socketio/blob/cb107ba6770fabb109dce173b74ab36ebe039045/socketio/src/socket.rs#L105

Deserializing into a `serde_json::Value` just for the sake of validation can be optimized by deserializing into something like [`serde::IgnoredAny`](https://docs.rs/serde/latest/serde/de/struct.IgnoredAny.html) because its deserialization does not hold any data or allocations.
Since `serde` is not yet included as a dependency, the question is if it should be imported just to be able to access its `IgnoredAny` type or alternatively the type could be copy-pasted into its own module so `serde` doesn't need to be imported but a bunch of boilerplate code would be added.

I'd be happy to PR the optimization, am just not sure which option is preferred.


Discussion / hints:
Actually, `serde` is already a transitive dependency at the very least because of `rust_engineio` so it should be fine to add it as a direct dependency.

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 47c9aea1..a4880e83 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1536,6 +1536,7 @@ dependencies = [
  "native-tls",
  "rand",
  "rust_engineio",
+ "serde",
  "serde_json",
  "thiserror",
  "tokio",
diff --git a/socketio/Cargo.toml b/socketio/Cargo.toml
index 2273e0b4..7cb5d341 100644
--- a/socketio/Cargo.toml
+++ b/socketio/Cargo.toml
@@ -26,6 +26,7 @@ tokio = { version = "1.16.1", optional = true }
 futures-util = { version = "0.3", default-features = false, features = ["sink"], optional = true }
 async-stream = { version = "0.3.5", optional = true }
 log = "0.4.17"
+serde = "1.0.163"
 
 [dev-dependencies]
 cargo-tarpaulin = "0.18.5"
diff --git a/socketio/src/asynchronous/socket.rs b/socketio/src/asynchronous/socket.rs
index 6bf0db21..970e4470 100644
--- a/socketio/src/asynchronous/socket.rs
+++ b/socketio/src/asynchronous/socket.rs
@@ -10,6 +10,8 @@ use futures_util::{Stream, StreamExt};
 use rust_engineio::{
     asynchronous::Client as EngineClient, Packet as EnginePacket, PacketId as EnginePacketId,
 };
+use serde::de::IgnoredAny;
+use serde_json::Value;
 use std::{
     fmt::Debug,
     pin::Pin,
@@ -107,13 +109,13 @@ impl Socket {
                     PacketId::BinaryEvent
                 },
                 nsp.to_owned(),
-                Some(serde_json::Value::String(event.into()).to_string()),
+                Some(Value::String(event.into()).to_string()),
                 id,
                 1,
                 Some(vec![bin_data]),
             )),
             Payload::String(str_data) => {
-                serde_json::from_str::<serde_json::Value>(&str_data)?;
+                serde_json::from_str::<IgnoredAny>(&str_data)?;
 
                 let payload = format!("[\"{}\",{}]", String::from(event), str_data);
 
diff --git a/socketio/src/packet.rs b/socketio/src/packet.rs
index a71b662a..13119787 100644
--- a/socketio/src/packet.rs
+++ b/socketio/src/packet.rs
@@ -1,5 +1,6 @@
 use crate::error::{Error, Result};
 use bytes::Bytes;
+use serde::de::IgnoredAny;
 
 use std::convert::TryFrom;
 use std::fmt::Write;
@@ -189,7 +190,7 @@ impl TryFrom<&Bytes> for Packet {
         }
 
         // validate json
-        serde_json::from_str::<serde_json::Value>(payload).map_err(Error::InvalidJson)?;
+        serde_json::from_str::<IgnoredAny>(payload).map_err(Error::InvalidJson)?;
 
         match packet.packet_type {
             PacketId::BinaryAck | PacketId::BinaryEvent => {
diff --git a/socketio/src/socket.rs b/socketio/src/socket.rs
index d387769d..9260b59a 100644
--- a/socketio/src/socket.rs
+++ b/socketio/src/socket.rs
@@ -2,6 +2,8 @@ use crate::error::{Error, Result};
 use crate::packet::{Packet, PacketId};
 use bytes::Bytes;
 use rust_engineio::{Client as EngineClient, Packet as EnginePacket, PacketId as EnginePacketId};
+use serde::de::IgnoredAny;
+use serde_json::Value;
 use std::convert::TryFrom;
 use std::sync::{atomic::AtomicBool, Arc};
 use std::{fmt::Debug, sync::atomic::Ordering};
@@ -96,13 +98,13 @@ impl Socket {
                     PacketId::BinaryEvent
                 },
                 nsp.to_owned(),
-                Some(serde_json::Value::String(event.into()).to_string()),
+                Some(Value::String(event.into()).to_string()),
                 id,
                 1,
                 Some(vec![bin_data]),
             )),
             Payload::String(str_data) => {
-                let payload = if serde_json::from_str::<serde_json::Value>(&str_data).is_ok() {
+                let payload = if serde_json::from_str::<IgnoredAny>(&str_data).is_ok() {
                     format!("[\"{}\",{}]", String::from(event), str_data)
                 } else {
                     format!("[\"{}\",\"{}\"]", String::from(event), str_data)


Test patch: